connection.h \
matchrule.c \
matchrule.h \
- registry.c \
- registry.h \
marshalers.c \
marshalers.h \
types.h \
if ENABLE_TESTS
TESTS = \
test-matchrule \
- test-registry \
test-stress \
$(NULL)
endif
noinst_PROGRAMS = $(TESTS)
-test_registry_SOURCES = \
- $(commonsrc) \
- test-registry.c \
- $(NULL)
-test_registry_CFLAGS = \
- $(AM_CFLAGS) \
- $(NULL)
-test_registry_LDADD = \
- $(AM_LDADD) \
- $(NULL)
-
test_matchrule_DEPENDENCIES = \
$(libibus) \
$(NULL)
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/* vim:set et sts=4: */
/* ibus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2008-2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "ibusimpl.h"
#include "marshalers.h"
#include "matchrule.h"
-#include "registry.h"
#include "types.h"
enum {
return;
}
- BusRegistry *registry = BUS_DEFAULT_REGISTRY;
- BusComponent *component = bus_registry_lookup_component_by_name (registry,
- name);
+ BusComponent *component = bus_ibus_impl_lookup_component_by_name (
+ BUS_DEFAULT_IBUS, name);
if (component == NULL || !bus_component_start (component, g_verbose)) {
g_dbus_method_invocation_return_error (invocation,
\fB\-r\fR, \fB\-\-replace\fR
if there is an old ibus\-daemon is running, it will be replaced.
.TP
-\fB\-t\fR, \fB\-\-re\-scan\fR
+\fB\-t\fR, \fB\-\-cache\fR=\fImode\fR [default is auto]
force to re\-scan components, and re\-create registry cache.
+auto, refresh, none is available.
.TP
\fB\-o\fR, \fB\-\-timeout\fR=\fItimeout\fR [default is 2000]
dbus reply timeout in milliseconds.
#include "global.h"
#include "inputcontext.h"
#include "panelproxy.h"
-#include "registry.h"
#include "server.h"
#include "types.h"
gboolean embed_preedit_text;
- BusRegistry *registry;
+ IBusRegistry *registry;
+
+ /* a list of BusComponent objects that are created from component XML
+ * files (or from the cache of them). */
+ GList *components;
+
+ /* a mapping from an engine name (e.g. 'pinyin') to the corresponding
+ * IBusEngineDesc object. */
+ GHashTable *engine_table;
BusInputContext *focused_context;
BusPanelProxy *panel;
*/
/* functions prototype */
-static void bus_ibus_impl_destroy (BusIBusImpl *ibus);
-static void bus_ibus_impl_service_method_call
+static void bus_ibus_impl_destroy (BusIBusImpl *ibus);
+static void bus_ibus_impl_service_method_call
(IBusService *service,
GDBusConnection *connection,
const gchar *sender,
const gchar *property_name,
GVariant *value,
GError **error);
+static void bus_ibus_impl_registry_init
+ (BusIBusImpl *ibus);
static void bus_ibus_impl_registry_changed
(BusIBusImpl *ibus);
+static void bus_ibus_impl_registry_destroy
+ (BusIBusImpl *ibus);
+static void bus_ibus_impl_component_name_owner_changed
+ (BusIBusImpl *ibus,
+ const gchar *name,
+ const gchar *old_name,
+ const gchar *new_name);
static void bus_ibus_impl_global_engine_changed
(BusIBusImpl *ibus);
static void bus_ibus_impl_set_context_engine_from_desc
}
static void
-_registry_changed_cb (BusRegistry *registry,
- BusIBusImpl *ibus)
+_registry_changed_cb (IBusRegistry *registry,
+ BusIBusImpl *ibus)
{
bus_ibus_impl_registry_changed (ibus);
}
}
}
- bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
+ bus_ibus_impl_component_name_owner_changed (ibus, name, old_name, new_name);
}
/**
ibus->contexts = NULL;
ibus->focused_context = NULL;
ibus->panel = NULL;
- ibus->registry = bus_registry_new ();
-
- g_signal_connect (ibus->registry,
- "changed",
- G_CALLBACK (_registry_changed_cb),
- ibus);
- bus_registry_start_monitor_changes (ibus->registry);
ibus->keymap = ibus_keymap_get ("us");
"name-owner-changed",
G_CALLBACK (_dbus_name_owner_changed_cb),
ibus);
+
+ bus_ibus_impl_registry_init (ibus);
}
/**
gint status;
gboolean flag;
- bus_registry_stop_all_components (ibus->registry);
+ g_list_foreach (ibus->components, (GFunc) bus_component_stop, NULL);
pid = 0;
timeout = 0;
ibus->fake_context = NULL;
}
+ bus_ibus_impl_registry_destroy (ibus);
+
IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
}
IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, engine_name);
if (desc == NULL) {
- desc = bus_registry_find_engine_by_name (ibus->registry, engine_name);
+ desc = (IBusEngineDesc *) g_hash_table_lookup (ibus->engine_table,
+ engine_name);
}
return desc;
}
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
- engines = bus_registry_get_engines (ibus->registry);
+ engines = g_hash_table_get_values (ibus->engine_table);
for (p = engines; p != NULL; p = p->next) {
g_variant_builder_add (
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
while (names[i] != NULL) {
- IBusEngineDesc *desc = bus_registry_find_engine_by_name (
- ibus->registry, names[i++]);
+ IBusEngineDesc *desc = (IBusEngineDesc *) g_hash_table_lookup (
+ ibus->engine_table, names[i++]);
if (desc == NULL)
continue;
g_variant_builder_add (
return ibus->keymap;
}
-BusRegistry *
-bus_ibus_impl_get_registry (BusIBusImpl *ibus)
+/**
+ * bus_ibus_impl_registry_init:
+ *
+ * Initialize IBusRegistry.
+ */
+static void
+bus_ibus_impl_registry_init (BusIBusImpl *ibus)
+{
+ GList *p;
+ GList *components;
+ IBusRegistry *registry = ibus_registry_new ();
+
+ ibus->registry = NULL;
+ ibus->components = NULL;
+ ibus->engine_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (g_strcmp0 (g_cache, "none") == 0) {
+ /* Only load registry, but not read and write cache. */
+ ibus_registry_load (registry);
+ }
+ else if (g_strcmp0 (g_cache, "refresh") == 0) {
+ /* Load registry and overwrite the cache. */
+ ibus_registry_load (registry);
+ ibus_registry_save_cache (registry, TRUE);
+ }
+ else if (g_strcmp0 (g_cache, "auto") == 0) {
+ /* Load registry from cache. If the cache does not exist or
+ * it is outdated, then generate it.
+ */
+ if (ibus_registry_load_cache (registry, FALSE) == FALSE ||
+ ibus_registry_check_modification (registry)) {
+
+ ibus_object_destroy (IBUS_OBJECT (registry));
+ registry = ibus_registry_new ();
+
+ if (ibus_registry_load_cache (registry, TRUE) == FALSE ||
+ ibus_registry_check_modification (registry)) {
+
+ ibus_object_destroy (IBUS_OBJECT (registry));
+ registry = ibus_registry_new ();
+ ibus_registry_load (registry);
+ ibus_registry_save_cache (registry, TRUE);
+ }
+ }
+ }
+
+ ibus->registry = registry;
+ components = ibus_registry_get_components (registry);
+
+ for (p = components; p != NULL; p = p->next) {
+ IBusComponent *component = (IBusComponent *) p->data;
+ BusComponent *buscomp = bus_component_new (component,
+ NULL /* factory */);
+ GList *engines = NULL;
+ GList *p1;
+
+ g_object_ref_sink (buscomp);
+ ibus->components = g_list_append (ibus->components, buscomp);
+
+ engines = bus_component_get_engines (buscomp);
+ for (p1 = engines; p1 != NULL; p1 = p1->next) {
+ IBusEngineDesc *desc = (IBusEngineDesc *) p1->data;
+ const gchar *name = ibus_engine_desc_get_name (desc);
+ if (g_hash_table_lookup (ibus->engine_table, name) == NULL) {
+ g_hash_table_insert (ibus->engine_table,
+ (gpointer) name,
+ desc);
+ } else {
+ g_message ("Engine %s is already registered by other component",
+ name);
+ }
+ }
+ g_list_free (engines);
+ }
+
+ g_list_free (components);
+
+ g_signal_connect (ibus->registry,
+ "changed",
+ G_CALLBACK (_registry_changed_cb),
+ ibus);
+ ibus_registry_start_monitor_changes (ibus->registry);
+}
+
+static void
+bus_ibus_impl_registry_destroy (BusIBusImpl *ibus)
{
+ g_list_free_full (ibus->components, g_object_unref);
+ ibus->components = NULL;
+
+ g_hash_table_destroy (ibus->engine_table);
+ ibus->engine_table = NULL;
+
+ ibus_object_destroy (IBUS_OBJECT (ibus->registry));
+ ibus->registry = NULL;
+}
+
+static gint
+_component_is_name_cb (BusComponent *component,
+ const gchar *name)
+{
+ g_assert (BUS_IS_COMPONENT (component));
+ g_assert (name);
+
+ return g_strcmp0 (bus_component_get_name (component), name);
+}
+
+static void
+bus_ibus_impl_component_name_owner_changed (BusIBusImpl *ibus,
+ const gchar *name,
+ const gchar *old_name,
+ const gchar *new_name)
+{
+ BusComponent *component;
+ BusFactoryProxy *factory;
g_assert (BUS_IS_IBUS_IMPL (ibus));
+ g_assert (name);
+ g_assert (old_name);
+ g_assert (new_name);
+
+ component = bus_ibus_impl_lookup_component_by_name (ibus, name);
- return ibus->registry;
+ if (component == NULL) {
+ /* name is a unique name, or a well-known name we don't know. */
+ return;
+ }
+
+ if (g_strcmp0 (old_name, "") != 0) {
+ /* the component is stopped. */
+ factory = bus_component_get_factory (component);
+
+ if (factory != NULL) {
+ ibus_proxy_destroy ((IBusProxy *) factory);
+ }
+ }
+
+ if (g_strcmp0 (new_name, "") != 0) {
+ /* the component is started. */
+ BusConnection *connection =
+ bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS,
+ new_name);
+ if (connection == NULL)
+ return;
+
+ factory = bus_factory_proxy_new (connection);
+ if (factory == NULL)
+ return;
+ bus_component_set_factory (component, factory);
+ g_object_unref (factory);
+ }
+}
+
+BusComponent *
+bus_ibus_impl_lookup_component_by_name (BusIBusImpl *ibus,
+ const gchar *name)
+{
+ GList *p;
+
+ g_assert (BUS_IS_IBUS_IMPL (ibus));
+ g_assert (name);
+
+ p = g_list_find_custom (ibus->components,
+ name,
+ (GCompareFunc) _component_is_name_cb);
+ if (p) {
+ return (BusComponent *) p->data;
+ }
+ else {
+ return NULL;
+ }
}
/**
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/* vim:set et sts=4: */
/* bus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2008-2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <ibus.h>
#include "connection.h"
+#include "component.h"
#include "inputcontext.h"
-#include "registry.h"
#include "factoryproxy.h"
#include "panelproxy.h"
#include "engineproxy.h"
(bus_ibus_impl_get_default ())
#define BUS_DEFAULT_KEYMAP \
(bus_ibus_impl_get_keymap (BUS_DEFAULT_IBUS))
-#define BUS_DEFAULT_REGISTRY \
- (bus_ibus_impl_get_registry (BUS_DEFAULT_IBUS))
G_BEGIN_DECLS
BusFactoryProxy *bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
const gchar *path);
IBusKeymap *bus_ibus_impl_get_keymap (BusIBusImpl *ibus);
-BusRegistry *bus_ibus_impl_get_registry (BusIBusImpl *ibus);
+BusComponent *bus_ibus_impl_lookup_component_by_name
+ (BusIBusImpl *ibus,
+ const gchar *name);
gboolean bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus);
gboolean bus_ibus_impl_is_embed_preedit_text
(BusIBusImpl *ibus);
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/* vim:set et sts=4: */
/* ibus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2008-2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
/* execute config component */
if (g_strcmp0 (config, "default") == 0) {
BusComponent *component;
- component = bus_registry_lookup_component_by_name (BUS_DEFAULT_REGISTRY, IBUS_SERVICE_CONFIG);
+ component = bus_ibus_impl_lookup_component_by_name (
+ BUS_DEFAULT_IBUS, IBUS_SERVICE_CONFIG);
if (component) {
bus_component_set_restart (component, restart);
}
/* execute panel component */
if (g_strcmp0 (panel, "default") == 0) {
BusComponent *component;
- component = bus_registry_lookup_component_by_name (BUS_DEFAULT_REGISTRY, IBUS_SERVICE_PANEL);
+ component = bus_ibus_impl_lookup_component_by_name (
+ BUS_DEFAULT_IBUS, IBUS_SERVICE_PANEL);
if (component) {
bus_component_set_restart (component, restart);
}
+++ /dev/null
-/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-/* vim:set et sts=4: */
-/* bus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
- *
- * 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 "registry.h"
-
-#include <gio/gio.h>
-#include <glib/gstdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dbusimpl.h"
-#include "global.h"
-#include "marshalers.h"
-#include "types.h"
-
-enum {
- CHANGED,
- LAST_SIGNAL,
-};
-
-static guint _signals[LAST_SIGNAL] = { 0 };
-
-struct _BusRegistry {
- IBusObject parent;
-
- /* instance members */
-
- /* a list of IBusObservedPath objects. */
- GList *observed_paths;
- /* a list of BusComponent objects that are created from component XML files (or from the cache of them). */
- GList *components;
- /* a mapping from an engine name (e.g. 'pinyin') to the corresponding IBusEngineDesc object. */
- GHashTable *engine_table;
- gboolean changed;
- /* a mapping from GFile to GFileMonitor. */
- GHashTable *monitor_table;
- guint monitor_timeout_id;
-};
-
-struct _BusRegistryClass {
- IBusObjectClass parent;
-
- /* class members */
-};
-
-/* functions prototype */
-static void bus_registry_destroy (BusRegistry *registry);
-static void bus_registry_load (BusRegistry *registry);
-static void bus_registry_load_in_dir (BusRegistry *registry,
- const gchar *dirname);
-static gboolean bus_registry_save_cache (BusRegistry *registry);
-static gboolean bus_registry_load_cache (BusRegistry *registry);
-static gboolean bus_registry_check_modification(BusRegistry *registry);
-static void bus_registry_remove_all (BusRegistry *registry);
-
-G_DEFINE_TYPE (BusRegistry, bus_registry, IBUS_TYPE_OBJECT)
-
-static void
-bus_registry_class_init (BusRegistryClass *class)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (class);
- IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
-
- _signals[CHANGED] =
- g_signal_new (I_("changed"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- 0, /* does not associate a method in this class. the "changed" signal would be handled in other classes. */
- NULL, NULL,
- bus_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_registry_destroy;
-}
-
-static void
-bus_registry_init (BusRegistry *registry)
-{
- GList *p;
- registry->observed_paths = NULL;
- registry->components = NULL;
- registry->engine_table = g_hash_table_new (g_str_hash, g_str_equal);
- registry->changed = FALSE;
- registry->monitor_table =
- g_hash_table_new_full (g_file_hash,
- (GEqualFunc) g_file_equal,
- (GDestroyNotify) g_object_unref,
- (GDestroyNotify) g_object_unref);
-
- if (g_strcmp0 (g_cache, "none") == 0) {
- /* Only load registry, but not read and write cache. */
- bus_registry_load (registry);
- }
- else if (g_strcmp0 (g_cache, "refresh") == 0) {
- /* Load registry and overwrite the cache. */
- bus_registry_load (registry);
- bus_registry_save_cache (registry);
- }
- else {
- /* Load registry from cache. If the cache does not exist or
- * it is outdated, then generate it.
- */
- if (bus_registry_load_cache (registry) == FALSE ||
- bus_registry_check_modification (registry)) {
- bus_registry_remove_all (registry);
- bus_registry_load (registry);
- bus_registry_save_cache (registry);
- }
- }
-
- for (p = registry->components; p != NULL; p = p->next) {
- BusComponent *comp = (BusComponent *) p->data;
- GList *engines = bus_component_get_engines (comp);
- GList *p1;
- for (p1 = engines; p1 != NULL; p1 = p1->next) {
- IBusEngineDesc *desc = (IBusEngineDesc *) p1->data;
- const gchar *name = ibus_engine_desc_get_name (desc);
- if (g_hash_table_lookup (registry->engine_table, name) == NULL) {
- g_hash_table_insert (registry->engine_table,
- (gpointer) name,
- desc);
- } else {
- g_message ("Engine %s is already registered by other component",
- name);
- }
- }
- g_list_free (engines);
- }
-}
-
-static void
-bus_registry_remove_all (BusRegistry *registry)
-{
- g_list_free_full (registry->observed_paths, g_object_unref);
- registry->observed_paths = NULL;
-
- g_list_free_full (registry->components, g_object_unref);
- registry->components = NULL;
-
- g_hash_table_remove_all (registry->engine_table);
- g_hash_table_remove_all (registry->monitor_table);
-}
-
-static void
-bus_registry_destroy (BusRegistry *registry)
-{
- bus_registry_remove_all (registry);
-
- g_hash_table_destroy (registry->engine_table);
- registry->engine_table = NULL;
-
- g_hash_table_destroy (registry->monitor_table);
- registry->monitor_table = NULL;
-
- if (registry->monitor_timeout_id > 0) {
- g_source_remove (registry->monitor_timeout_id);
- registry->monitor_timeout_id = 0;
- }
-
- IBUS_OBJECT_CLASS (bus_registry_parent_class)->destroy (IBUS_OBJECT (registry));
-}
-
-/**
- * bus_registry_load:
- *
- * Read all XML files in the PKGDATADIR (typically /usr/share/ibus/components/ *.xml) and update the registry object.
- */
-static void
-bus_registry_load (BusRegistry *registry)
-{
- g_assert (BUS_IS_REGISTRY (registry));
-
- const gchar *envstr;
- GPtrArray *path;
- gchar **d, **search_path;
-
- path = g_ptr_array_new();
-
- envstr = g_getenv ("IBUS_COMPONENT_PATH");
- if (envstr) {
- gchar **dirs = g_strsplit (envstr, G_SEARCHPATH_SEPARATOR_S, 0);
- for (d = dirs; *d != NULL; d++)
- g_ptr_array_add (path, *d);
- g_free (dirs);
- } else {
- gchar *dirname;
-
- dirname = g_build_filename (PKGDATADIR, "component", NULL);
- g_ptr_array_add (path, dirname);
-
-#if 0
- /* FIXME Should we support install some IME in user dir? */
- dirname = g_build_filename (g_get_user_data_dir (),
- "ibus", "component",
- NULL);
- g_ptr_array_add (path, dirname);
-#endif
- }
-
- g_ptr_array_add (path, NULL);
- search_path = (gchar **) g_ptr_array_free (path, FALSE);
- for (d = search_path; *d != NULL; d++) {
- IBusObservedPath *observed_path = ibus_observed_path_new (*d, TRUE);
-
- registry->observed_paths = g_list_append (registry->observed_paths,
- observed_path);
-
- bus_registry_load_in_dir (registry, *d);
- }
- g_strfreev (search_path);
-}
-
-#define g_string_append_indent(string, indent) \
- { \
- gint i; \
- for (i = 0; i < (indent); i++) { \
- g_string_append (string, " "); \
- } \
- }
-
-static gboolean
-bus_registry_load_cache (BusRegistry *registry)
-{
- g_assert (BUS_IS_REGISTRY (registry));
-
- gchar *filename;
- XMLNode *node;
- GList *p;
-
- filename = g_build_filename (g_get_user_cache_dir (), "ibus", "bus", "registry.xml", NULL);
- node = ibus_xml_parse_file (filename);
- g_free (filename);
-
- if (node == NULL) {
- return FALSE;
- }
-
- if (g_strcmp0 (node->name, "ibus-registry") != 0) {
- ibus_xml_free (node);
- return FALSE;
- }
-
- for (p = node->sub_nodes; p != NULL; p = p->next) {
- XMLNode *sub_node = (XMLNode *) p->data;
-
- if (g_strcmp0 (sub_node->name, "observed-paths") == 0) {
- GList *pp;
- for (pp = sub_node->sub_nodes; pp != NULL; pp = pp->next) {
- IBusObservedPath *path;
- path = ibus_observed_path_new_from_xml_node (pp->data, FALSE);
- if (path) {
- g_object_ref_sink (path);
- registry->observed_paths = g_list_append (registry->observed_paths, path);
- }
- }
- continue;
- }
- if (g_strcmp0 (sub_node->name, "components") == 0) {
- GList *pp;
- for (pp = sub_node->sub_nodes; pp != NULL; pp = pp->next) {
- IBusComponent *component;
- component = ibus_component_new_from_xml_node (pp->data);
- if (component) {
- BusComponent *buscomp = bus_component_new (component,
- NULL /* factory */);
- g_object_ref_sink (buscomp);
- registry->components =
- g_list_append (registry->components, buscomp);
- }
- }
-
- continue;
- }
- g_warning ("Unknown element <%s>", sub_node->name);
- }
-
- ibus_xml_free (node);
- return TRUE;
-}
-
-static gboolean
-bus_registry_check_modification (BusRegistry *registry)
-{
- GList *p;
-
- for (p = registry->observed_paths; p != NULL; p = p->next) {
- if (ibus_observed_path_check_modification ((IBusObservedPath *) p->data))
- return TRUE;
- }
-
- for (p = registry->components; p != NULL; p = p->next) {
- if (ibus_component_check_modification (bus_component_get_component ((BusComponent *) p->data)))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-bus_registry_save_cache (BusRegistry *registry)
-{
- g_assert (BUS_IS_REGISTRY (registry));
-
- gchar *cachedir;
- gchar *filename;
- GString *output;
- GList *p;
- FILE *pf;
- size_t items = 0;
-
- cachedir = g_build_filename (g_get_user_cache_dir (), "ibus", "bus", NULL);
- filename = g_build_filename (cachedir, "registry.xml", NULL);
- g_mkdir_with_parents (cachedir, 0775);
- pf = g_fopen (filename, "w");
- g_free (filename);
- g_free (cachedir);
-
- if (pf == NULL) {
- g_warning ("create registry.xml failed");
- return FALSE;
- }
-
- output = g_string_new ("");
- g_string_append (output, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
- g_string_append (output, "<!-- \n"
- " This file was generated by ibus-daemon. Please don't modify it.\n"
- " -->\n");
- g_string_append (output, "<ibus-registry>\n");
-
- if (registry->observed_paths) {
- g_string_append_indent (output, 1);
- g_string_append (output, "<observed-paths>\n");
- for (p = registry->observed_paths; p != NULL; p = p->next) {
- ibus_observed_path_output ((IBusObservedPath *) p->data,
- output, 2);
- }
- g_string_append_indent (output, 1);
- g_string_append (output, "</observed-paths>\n");
- }
-
- if (registry->components) {
- g_string_append_indent (output, 1);
- g_string_append (output, "<components>\n");
- for (p = registry->components; p != NULL; p = p->next) {
- ibus_component_output (bus_component_get_component ((BusComponent *) p->data),
- output, 2);
- }
- g_string_append_indent (output, 1);
- g_string_append (output, "</components>\n");
- }
-
- g_string_append (output, "</ibus-registry>\n");
- items = fwrite (output->str, output->len, 1, pf);
- g_string_free (output, TRUE);
- fclose (pf);
- return (items == 1 ? TRUE : FALSE);
-}
-
-/**
- * bus_registry_load_in_dir:
- *
- * Read all XML files in dirname, create a BusComponent object for each file, and add the component objects to the registry.
- */
-static void
-bus_registry_load_in_dir (BusRegistry *registry,
- const gchar *dirname)
-{
- g_assert (BUS_IS_REGISTRY (registry));
- g_assert (dirname);
-
- GError *error = NULL;
- GDir *dir;
- const gchar *filename;
-
- dir = g_dir_open (dirname, 0, &error);
-
- if (dir == NULL) {
- g_warning ("Unable open directory %s : %s", dirname, error->message);
- g_error_free (error);
- return;
- }
-
- while ((filename = g_dir_read_name (dir)) != NULL) {
- glong size;
- gchar *path;
- IBusComponent *component;
-
- size = g_utf8_strlen (filename, -1);
- if (g_strcmp0 (MAX (filename, filename + size - 4), ".xml") != 0)
- continue;
-
- path = g_build_filename (dirname, filename, NULL);
- component = ibus_component_new_from_file (path);
- if (component != NULL) {
- BusComponent *buscomp = bus_component_new (component,
- NULL /* factory */);
- g_object_ref_sink (buscomp);
- registry->components =
- g_list_append (registry->components, buscomp);
- }
-
- g_free (path);
- }
-
- g_dir_close (dir);
-}
-
-
-BusRegistry *
-bus_registry_new (void)
-{
- BusRegistry *registry;
- registry = (BusRegistry *) g_object_new (BUS_TYPE_REGISTRY, NULL);
- return registry;
-}
-
-static gint
-bus_register_component_is_name_cb (BusComponent *component,
- const gchar *name)
-{
- g_assert (BUS_IS_COMPONENT (component));
- g_assert (name);
-
- return g_strcmp0 (bus_component_get_name (component), name);
-}
-
-BusComponent *
-bus_registry_lookup_component_by_name (BusRegistry *registry,
- const gchar *name)
-{
- g_assert (BUS_IS_REGISTRY (registry));
- g_assert (name);
-
- GList *p;
- p = g_list_find_custom (registry->components,
- name,
- (GCompareFunc) bus_register_component_is_name_cb);
- if (p) {
- return (BusComponent *) p->data;
- }
- else {
- return NULL;
- }
-}
-
-GList *
-bus_registry_get_components (BusRegistry *registry)
-{
- g_assert (BUS_IS_REGISTRY (registry));
-
- return g_list_copy (registry->components);
-}
-
-GList *
-bus_registry_get_engines (BusRegistry *registry)
-{
- g_assert (BUS_IS_REGISTRY (registry));
-
- return g_hash_table_get_values (registry->engine_table);
-}
-
-GList *
-bus_registry_get_engines_by_language (BusRegistry *registry,
- const gchar *language)
-{
- g_assert (BUS_IS_REGISTRY (registry));
- g_assert (language);
-
- gint n;
- GList *p1, *p2, *engines;
-
- n = strlen (language);
-
- p1 = bus_registry_get_engines (registry);
-
- engines = NULL;
-
- for (p2 = p1; p2 != NULL; p2 = p2->next) {
- IBusEngineDesc *desc = (IBusEngineDesc *) p2->data;
- if (strncmp (ibus_engine_desc_get_language (desc), language, n) == 0) {
- engines = g_list_append (engines, desc);
- }
- }
-
- g_list_free (p1);
- return engines;
-}
-
-IBusEngineDesc *
-bus_registry_find_engine_by_name (BusRegistry *registry,
- const gchar *name)
-{
- g_assert (BUS_IS_REGISTRY (registry));
- g_assert (name);
-
- return (IBusEngineDesc *) g_hash_table_lookup (registry->engine_table, name);
-}
-
-void
-bus_registry_stop_all_components (BusRegistry *registry)
-{
- g_assert (BUS_IS_REGISTRY (registry));
-
- g_list_foreach (registry->components, (GFunc) bus_component_stop, NULL);
-
-}
-
-static gboolean
-_monitor_timeout_cb (BusRegistry *registry)
-{
- g_hash_table_remove_all (registry->monitor_table);
- registry->changed = TRUE;
- g_signal_emit (registry, _signals[CHANGED], 0);
- registry->monitor_timeout_id = 0;
- return FALSE;
-}
-
-static void
-_monitor_changed_cb (GFileMonitor *monitor,
- GFile *file,
- GFile *other_file,
- GFileMonitorEvent event_type,
- BusRegistry *registry)
-{
- g_assert (BUS_IS_REGISTRY (registry));
-
- if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
- event_type != G_FILE_MONITOR_EVENT_DELETED &&
- event_type != G_FILE_MONITOR_EVENT_CREATED &&
- event_type != G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED)
- return;
-
- /* Merge successive file changes into one, with a low priority
- timeout handler. */
- if (registry->monitor_timeout_id > 0)
- return;
-
- registry->monitor_timeout_id =
- g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
- 5000,
- (GSourceFunc) _monitor_timeout_cb,
- g_object_ref (registry),
- (GDestroyNotify) g_object_unref);
-}
-
-/**
- * bus_registry_start_monitor_changes:
- *
- * Start the monitor thread.
- */
-void
-bus_registry_start_monitor_changes (BusRegistry *registry)
-{
- GList *observed_paths, *p;
-
- g_assert (BUS_IS_REGISTRY (registry));
-
- g_hash_table_remove_all (registry->monitor_table);
-
- observed_paths = g_list_copy (registry->observed_paths);
- for (p = registry->components; p != NULL; p = p->next) {
- BusComponent *buscomp = (BusComponent *) p->data;
- IBusComponent *component = bus_component_get_component (buscomp);
- GList *component_observed_paths =
- ibus_component_get_observed_paths (component);
- observed_paths = g_list_concat (observed_paths,
- component_observed_paths);
- }
-
- for (p = observed_paths; p != NULL; p = p->next) {
- IBusObservedPath *path = (IBusObservedPath *) p->data;
- GFile *file = g_file_new_for_path (path->path);
- if (g_hash_table_lookup (registry->monitor_table,file) == NULL) {
- GFileMonitor *monitor;
- GError *error;
-
- error = NULL;
- monitor = g_file_monitor (file,
- G_FILE_MONITOR_NONE,
- NULL,
- &error);
-
- if (monitor != NULL) {
- g_signal_connect (monitor, "changed",
- G_CALLBACK (_monitor_changed_cb),
- registry);
-
- g_hash_table_replace (registry->monitor_table,
- g_object_ref (file),
- monitor);
- } else {
- g_warning ("Can't monitor directory %s: %s",
- path->path,
- error->message);
- g_error_free (error);
- }
- }
- g_object_unref (file);
- }
- g_list_free (observed_paths);
-}
-
-gboolean
-bus_registry_is_changed (BusRegistry *registry)
-{
- g_assert (BUS_IS_REGISTRY (registry));
- return (registry->changed != 0);
-}
-
-void
-bus_registry_name_owner_changed (BusRegistry *registry,
- const gchar *name,
- const gchar *old_name,
- const gchar *new_name)
-{
- g_assert (BUS_IS_REGISTRY (registry));
- g_assert (name);
- g_assert (old_name);
- g_assert (new_name);
-
- BusComponent *component;
- BusFactoryProxy *factory;
-
- component = bus_registry_lookup_component_by_name (registry, name);
-
- if (component == NULL) {
- /* name is a unique name, or a well-known name we don't know. */
- return;
- }
-
- if (g_strcmp0 (old_name, "") != 0) {
- /* the component is stopped. */
- factory = bus_component_get_factory (component);
-
- if (factory != NULL) {
- ibus_proxy_destroy ((IBusProxy *) factory);
- }
- }
-
- if (g_strcmp0 (new_name, "") != 0) {
- /* the component is started. */
- BusConnection *connection =
- bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS,
- new_name);
- if (connection == NULL)
- return;
-
- factory = bus_factory_proxy_new (connection);
- if (factory == NULL)
- return;
- bus_component_set_factory (component, factory);
- g_object_unref (factory);
- }
-}
+++ /dev/null
-/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-/* vim:set et sts=4: */
-/* bus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
- *
- * 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 __BUS_REGISTRY_H_
-#define __BUS_REGISTRY_H_
-
-#include <ibus.h>
-#include "component.h"
-
-/*
- * Type macros.
- */
-
-/* define GOBJECT macros */
-#define BUS_TYPE_REGISTRY \
- (bus_registry_get_type ())
-#define BUS_REGISTRY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUS_TYPE_REGISTRY, BusRegistry))
-#define BUS_REGISTRY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), BUS_TYPE_REGISTRY, BusRegistryClass))
-#define BUS_IS_REGISTRY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUS_TYPE_REGISTRY))
-#define BUS_IS_REGISTRY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), BUS_TYPE_REGISTRY))
-#define BUS_REGISTRY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_REGISTRY, BusRegistryClass))
-
-G_BEGIN_DECLS
-
-typedef struct _BusRegistry BusRegistry;
-typedef struct _BusRegistryClass BusRegistryClass;
-
-GType bus_registry_get_type (void);
-BusRegistry *bus_registry_new (void);
-
-/**
- * bus_registry_get_components:
- * @returns: a list of BusComponent objects. The caller has to call g_list_free for the returned list.
- */
-GList *bus_registry_get_components (BusRegistry *registry);
-
-/**
- * bus_registry_get_engines:
- * @returns: a list of all IBusEngineDesc objects available. The caller has to call g_list_free for the returned list.
- */
-GList *bus_registry_get_engines (BusRegistry *registry);
-
-/**
- * bus_registry_get_engines_by_language:
- * @language: a language name like 'ja'
- * @returns: a list of IBusEngineDesc objects for the language. The caller has to call g_list_free for the returned list.
- */
-GList *bus_registry_get_engines_by_language
- (BusRegistry *registry,
- const gchar *language);
-
-/**
- * bus_registry_stop_all_components:
- *
- * Terminate all component processes.
- */
-void bus_registry_stop_all_components
- (BusRegistry *registry);
-
-/**
- * bus_registry_lookup_component_by_name:
- * @name: a component name such as 'org.freedesktop.IBus.Panel' and 'com.google.IBus.Mozc'
- * @returns: a BusComponent object, or NULL if such component is not found.
- */
-BusComponent *bus_registry_lookup_component_by_name
- (BusRegistry *registry,
- const gchar *name);
-
-/**
- * bus_registry_find_engine_by_name:
- * @name: an engine name like 'pinyin'
- * @returns: an IBusEngineDesc object, or NULL if not found.
- */
-IBusEngineDesc *bus_registry_find_engine_by_name
- (BusRegistry *registry,
- const gchar *name);
-
-/**
- * bus_registry_name_owner_changed:
- * @name: a unique or well-known name like ":1.1", "org.freedesktop.IBus.Config", "com.google.IBus.Mozc".
- * @old_name: a unique name like ":1.1", or empty string "" when the client is started.
- * @new_name: a unique name like ":1.1", or empty string "" when the client is stopped.
- *
- * Handle the "name-owner-changed" glib signal from dbusimpl. If a component is stopped, remove a BusFactoryProxy object from the
- * bus for the component. If a component is started, create a new BusFactoryProxy object for the bus.
- */
-void bus_registry_name_owner_changed
- (BusRegistry *registry,
- const gchar *name,
- const gchar *old_name,
- const gchar *new_name);
-
-void bus_registry_start_monitor_changes
- (BusRegistry *registry);
-gboolean bus_registry_is_changed (BusRegistry *registry);
-
-G_END_DECLS
-#endif
-
+++ /dev/null
-/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-#include "registry.h"
-
-int main()
-{
-#if !GLIB_CHECK_VERSION(2,35,0)
- g_type_init ();
-#endif
- BusRegistry *registry = bus_registry_new ();
- g_object_unref (registry);
- return 0;
-}
<xi:include href="xml/ibusconfig.xml"/>
<xi:include href="xml/ibusconfigservice.xml"/>
<xi:include href="xml/ibusobservedpath.xml"/>
+ <xi:include href="xml/ibusregistry.xml"/>
<xi:include href="xml/ibusversion.xml"/>
<xi:include href="xml/ibusxml.xml"/>
</chapter>
ibus_prop_list_get_type
ibus_input_context_get_type
ibus_observed_path_get_type
+ibus_registry_get_type
#
# ibus - The Input Bus
#
-# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com>
-# Copyright (c) 2007-2010 Red Hat, Inc.
+# Copyright (c) 2007-2013 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
CLEANFILES =
# C preprocessor flags
-AM_CPPFLAGS = \
- -DG_LOG_DOMAIN=\"IBUS\" \
- @GLIB2_CFLAGS@ \
- @GOBJECT2_CFLAGS@ \
- @GIO2_CFLAGS@ \
- -DIBUS_DATA_DIR=\"$(pkgdatadir)\" \
- -DIBUS_DISABLE_DEPRECATION_WARNINGS \
- -DIBUS_COMPILATION \
- -DISOCODES_PREFIX=\"$(ISOCODES_PREFIX)\" \
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"IBUS\" \
+ @GLIB2_CFLAGS@ \
+ @GOBJECT2_CFLAGS@ \
+ @GIO2_CFLAGS@ \
+ -DIBUS_CACHE_DIR=\""$(localstatedir)/cache/ibus"\" \
+ -DIBUS_DATA_DIR=\"$(pkgdatadir)\" \
+ -DIBUS_DISABLE_DEPRECATION_WARNINGS \
+ -DIBUS_COMPILATION \
+ -DISOCODES_PREFIX=\"$(ISOCODES_PREFIX)\" \
$(NULL)
# ibus library
ibuscomponent.c \
ibusutil.c \
ibusenginesimple.c \
+ ibusregistry.c \
$(NULL)
libibus_1_0_la_SOURCES = \
ibusmarshalers.c \
ibuscomponent.h \
ibusutil.h \
ibusenginesimple.h \
+ ibusregistry.h \
$(NULL)
ibusincludedir = $(includedir)/ibus-@IBUS_API_VERSION@
ibus_public_headers = \
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/* vim:set et sts=4: */
/* ibus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2008-2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <ibusconfigservice.h>
#include <ibuspanelservice.h>
#include <ibusutil.h>
+#include <ibusregistry.h>
#ifndef IBUS_DISABLE_DEPRECATED
#include <ibuskeysyms-compat.h>
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/* vim:set et sts=4: */
+/* bus - The Input Bus
+ * Copyright (C) 2013 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * 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 <glib/gstdio.h>
+#include <string.h>
+
+#include "ibusinternal.h"
+#include "ibusmarshalers.h"
+#include "ibusregistry.h"
+
+enum {
+ CHANGED,
+ LAST_SIGNAL,
+};
+
+static guint _signals[LAST_SIGNAL] = { 0 };
+
+struct _IBusRegistryPrivate {
+ /* a list of IBusObservedPath objects. */
+ GList *observed_paths;
+
+ /* a list of IBusComponent objects that are created from component XML
+ * files (or from the cache of them). */
+ GList *components;
+
+ gboolean changed;
+
+ /* a mapping from GFile to GFileMonitor. */
+ GHashTable *monitor_table;
+
+ guint monitor_timeout_id;
+};
+
+#define IBUS_REGISTRY_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_REGISTRY, IBusRegistryPrivate))
+
+/* functions prototype */
+static void ibus_registry_destroy (IBusRegistry *registry);
+static void ibus_registry_remove_all (IBusRegistry *registry);
+
+G_DEFINE_TYPE (IBusRegistry, ibus_registry, IBUS_TYPE_OBJECT)
+
+static void
+ibus_registry_class_init (IBusRegistryClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
+
+ ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_registry_destroy;
+
+ g_type_class_add_private (class, sizeof (IBusRegistryPrivate));
+
+ /* install signals */
+ /**
+ * IBusRegistry::changed:
+ * @registry: An #IBusRegistry.
+ *
+ * Emitted when any observed paths are changed.
+ * A method is not associated in this class. the "changed"
+ * signal would be handled in other classes.
+ *
+ * See also: ibus_registry_start_monitor_changes().
+ */
+ _signals[CHANGED] =
+ g_signal_new (I_("changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ _ibus_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+static void
+ibus_registry_init (IBusRegistry *registry)
+{
+ registry->priv = IBUS_REGISTRY_GET_PRIVATE (registry);
+
+ registry->priv->observed_paths = NULL;
+ registry->priv->components = NULL;
+ registry->priv->changed = FALSE;
+ registry->priv->monitor_table =
+ g_hash_table_new_full (g_file_hash,
+ (GEqualFunc) g_file_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) g_object_unref);
+}
+
+static void
+ibus_registry_destroy (IBusRegistry *registry)
+{
+ ibus_registry_remove_all (registry);
+
+ g_hash_table_destroy (registry->priv->monitor_table);
+ registry->priv->monitor_table = NULL;
+
+ if (registry->priv->monitor_timeout_id > 0) {
+ g_source_remove (registry->priv->monitor_timeout_id);
+ registry->priv->monitor_timeout_id = 0;
+ }
+
+ IBUS_OBJECT_CLASS (ibus_registry_parent_class)->
+ destroy (IBUS_OBJECT (registry));
+}
+
+/**
+ * ibus_registry_remove_all:
+ *
+ * Remove the loaded registry.
+ */
+static void
+ibus_registry_remove_all (IBusRegistry *registry)
+{
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ g_list_free_full (registry->priv->observed_paths, g_object_unref);
+ registry->priv->observed_paths = NULL;
+
+ g_list_free_full (registry->priv->components, g_object_unref);
+ registry->priv->components = NULL;
+}
+
+void
+ibus_registry_load (IBusRegistry *registry)
+{
+ const gchar *envstr;
+ GPtrArray *path;
+ gchar **d, **search_path;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ path = g_ptr_array_new();
+
+ envstr = g_getenv ("IBUS_COMPONENT_PATH");
+ if (envstr) {
+ gchar **dirs = g_strsplit (envstr, G_SEARCHPATH_SEPARATOR_S, 0);
+ for (d = dirs; *d != NULL; d++)
+ g_ptr_array_add (path, *d);
+ g_free (dirs);
+ } else {
+ gchar *dirname;
+
+ dirname = g_build_filename (IBUS_DATA_DIR, "component", NULL);
+ g_ptr_array_add (path, dirname);
+
+#if 0
+ /* FIXME Should we support install some IME in user dir? */
+ dirname = g_build_filename (g_get_user_data_dir (),
+ "ibus", "component",
+ NULL);
+ g_ptr_array_add (path, dirname);
+#endif
+ }
+
+ g_ptr_array_add (path, NULL);
+ search_path = (gchar **) g_ptr_array_free (path, FALSE);
+ for (d = search_path; *d != NULL; d++) {
+ ibus_registry_load_in_dir (registry, *d);
+ }
+ g_strfreev (search_path);
+}
+
+gboolean
+ibus_registry_load_cache (IBusRegistry *registry, gboolean is_user)
+{
+ gchar *filename;
+ gboolean retval;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ if (is_user) {
+ filename = g_build_filename (g_get_user_cache_dir (),
+ "ibus", "bus", "registry.xml", NULL);
+ } else {
+ filename = g_build_filename (IBUS_CACHE_DIR,
+ "bus", "registry.xml", NULL);
+ }
+
+ retval = ibus_registry_load_cache_file (registry, filename);
+ g_free (filename);
+
+ return retval;
+}
+
+gboolean
+ibus_registry_load_cache_file (IBusRegistry *registry, const gchar *filename)
+{
+ XMLNode *node;
+ GList *p;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+ g_assert (filename != NULL);
+
+ node = ibus_xml_parse_file (filename);
+
+ if (node == NULL) {
+ return FALSE;
+ }
+
+ if (g_strcmp0 (node->name, "ibus-registry") != 0) {
+ ibus_xml_free (node);
+ return FALSE;
+ }
+
+ for (p = node->sub_nodes; p != NULL; p = p->next) {
+ XMLNode *sub_node = (XMLNode *) p->data;
+
+ if (g_strcmp0 (sub_node->name, "observed-paths") == 0) {
+ GList *pp;
+ for (pp = sub_node->sub_nodes; pp != NULL; pp = pp->next) {
+ IBusObservedPath *path;
+ path = ibus_observed_path_new_from_xml_node (pp->data, FALSE);
+ if (path) {
+ g_object_ref_sink (path);
+ registry->priv->observed_paths =
+ g_list_append (registry->priv->observed_paths,
+ path);
+ }
+ }
+ continue;
+ }
+ if (g_strcmp0 (sub_node->name, "components") == 0) {
+ GList *pp;
+ for (pp = sub_node->sub_nodes; pp != NULL; pp = pp->next) {
+ IBusComponent *component;
+ component = ibus_component_new_from_xml_node (pp->data);
+ if (component) {
+ g_object_ref_sink (component);
+ registry->priv->components =
+ g_list_append (registry->priv->components, component);
+ }
+ }
+
+ continue;
+ }
+ g_warning ("Unknown element <%s>", sub_node->name);
+ }
+
+ ibus_xml_free (node);
+ return TRUE;
+}
+
+gboolean
+ibus_registry_check_modification (IBusRegistry *registry)
+{
+ GList *p;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ for (p = registry->priv->observed_paths; p != NULL; p = p->next) {
+ if (ibus_observed_path_check_modification (
+ (IBusObservedPath *) p->data))
+ return TRUE;
+ }
+
+ for (p = registry->priv->components; p != NULL; p = p->next) {
+ if (ibus_component_check_modification ((IBusComponent *) p->data))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+ibus_registry_save_cache (IBusRegistry *registry, gboolean is_user)
+{
+ gchar *filename;
+ gboolean retval;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ if (is_user) {
+ filename = g_build_filename (g_get_user_cache_dir (),
+ "ibus", "bus", "registry.xml", NULL);
+ } else {
+ filename = g_build_filename (IBUS_CACHE_DIR,
+ "bus", "registry.xml", NULL);
+ }
+
+ retval = ibus_registry_save_cache_file (registry, filename);
+ g_free (filename);
+
+ return retval;
+}
+
+gboolean
+ibus_registry_save_cache_file (IBusRegistry *registry, const gchar *filename)
+{
+ gchar *cachedir;
+ const gchar *user_cachedir;
+ gboolean is_user = TRUE;
+ GString *output;
+ FILE *pf;
+ size_t items = 0;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+ g_assert (filename != NULL);
+
+ cachedir = g_path_get_dirname (filename);
+ g_mkdir_with_parents (cachedir, 0775);
+ g_free (cachedir);
+ pf = g_fopen (filename, "w");
+
+ if (pf == NULL) {
+ g_warning ("create %s failed", filename);
+ return FALSE;
+ }
+
+ output = g_string_new ("");
+
+ ibus_registry_output (registry, output, 1);
+
+ items = fwrite (output->str, output->len, 1, pf);
+ g_string_free (output, TRUE);
+ fclose (pf);
+
+ user_cachedir = g_get_user_cache_dir ();
+ is_user = (strncmp (user_cachedir, filename, strlen (user_cachedir)) == 0);
+
+ if (!is_user) {
+ g_chmod (filename, 0644);
+ }
+
+ return (items == 1 ? TRUE : FALSE);
+}
+
+#define g_string_append_indent(string, indent) \
+ { \
+ gint i; \
+ for (i = 0; i < (indent); i++) { \
+ g_string_append (string, " "); \
+ } \
+ }
+
+void
+ibus_registry_output (IBusRegistry *registry, GString *output, int indent)
+{
+ GList *p;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+ g_return_if_fail (output != NULL);
+
+ g_string_append (output, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ g_string_append (output, "<!-- \n"
+ " This file was generated by ibus-daemon. "
+ "Please don't modify it.\n"
+ " -->\n");
+ g_string_append (output, "<ibus-registry>\n");
+
+ if (registry->priv->observed_paths) {
+ g_string_append_indent (output, indent);
+ g_string_append (output, "<observed-paths>\n");
+ for (p = registry->priv->observed_paths; p != NULL; p = p->next) {
+ ibus_observed_path_output ((IBusObservedPath *) p->data,
+ output, indent * 2);
+ }
+ g_string_append_indent (output, indent);
+ g_string_append (output, "</observed-paths>\n");
+ }
+
+ if (registry->priv->components) {
+ g_string_append_indent (output, indent);
+ g_string_append (output, "<components>\n");
+ for (p = registry->priv->components; p != NULL; p = p->next) {
+ ibus_component_output ((IBusComponent *) p->data,
+ output, indent * 2);
+ }
+ g_string_append_indent (output, indent);
+ g_string_append (output, "</components>\n");
+ }
+
+ g_string_append (output, "</ibus-registry>\n");
+}
+
+void
+ibus_registry_load_in_dir (IBusRegistry *registry,
+ const gchar *dirname)
+{
+ GError *error = NULL;
+ GDir *dir;
+ IBusObservedPath *observed_path = NULL;
+ const gchar *filename;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+ g_assert (dirname);
+
+ dir = g_dir_open (dirname, 0, &error);
+
+ if (dir == NULL) {
+ g_warning ("Unable open directory %s : %s", dirname, error->message);
+ g_error_free (error);
+ return;
+ }
+
+ observed_path = ibus_observed_path_new (dirname, TRUE);
+
+ registry->priv->observed_paths =
+ g_list_append (registry->priv->observed_paths,
+ observed_path);
+
+ while ((filename = g_dir_read_name (dir)) != NULL) {
+ glong size;
+ gchar *path;
+ IBusComponent *component;
+
+ size = g_utf8_strlen (filename, -1);
+ if (g_strcmp0 (MAX (filename, filename + size - 4), ".xml") != 0)
+ continue;
+
+ path = g_build_filename (dirname, filename, NULL);
+ component = ibus_component_new_from_file (path);
+ if (component != NULL) {
+ g_object_ref_sink (component);
+ registry->priv->components =
+ g_list_append (registry->priv->components, component);
+ }
+
+ g_free (path);
+ }
+
+ g_dir_close (dir);
+}
+
+
+IBusRegistry *
+ibus_registry_new (void)
+{
+ IBusRegistry *registry;
+ registry = (IBusRegistry *) g_object_new (IBUS_TYPE_REGISTRY, NULL);
+ return registry;
+}
+
+GList *
+ibus_registry_get_components (IBusRegistry *registry)
+{
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ return g_list_copy (registry->priv->components);
+}
+
+GList *
+ibus_registry_get_observed_paths (IBusRegistry *registry)
+{
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ return g_list_copy (registry->priv->observed_paths);
+}
+
+static gboolean
+_monitor_timeout_cb (IBusRegistry *registry)
+{
+ g_hash_table_remove_all (registry->priv->monitor_table);
+ registry->priv->changed = TRUE;
+ g_signal_emit (registry, _signals[CHANGED], 0);
+ registry->priv->monitor_timeout_id = 0;
+ return FALSE;
+}
+
+static void
+_monitor_changed_cb (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ IBusRegistry *registry)
+{
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
+ event_type != G_FILE_MONITOR_EVENT_DELETED &&
+ event_type != G_FILE_MONITOR_EVENT_CREATED &&
+ event_type != G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED)
+ return;
+
+ /* Merge successive file changes into one, with a low priority
+ timeout handler. */
+ if (registry->priv->monitor_timeout_id > 0)
+ return;
+
+ registry->priv->monitor_timeout_id =
+ g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
+ 5000,
+ (GSourceFunc) _monitor_timeout_cb,
+ g_object_ref (registry),
+ (GDestroyNotify) g_object_unref);
+}
+
+void
+ibus_registry_start_monitor_changes (IBusRegistry *registry)
+{
+ GList *observed_paths, *p;
+
+ g_assert (IBUS_IS_REGISTRY (registry));
+
+ g_hash_table_remove_all (registry->priv->monitor_table);
+
+ observed_paths = g_list_copy (registry->priv->observed_paths);
+ for (p = registry->priv->components; p != NULL; p = p->next) {
+ IBusComponent *component = (IBusComponent *) p->data;
+ GList *component_observed_paths =
+ ibus_component_get_observed_paths (component);
+ observed_paths = g_list_concat (observed_paths,
+ component_observed_paths);
+ }
+
+ for (p = observed_paths; p != NULL; p = p->next) {
+ IBusObservedPath *path = (IBusObservedPath *) p->data;
+ GFile *file = g_file_new_for_path (path->path);
+ if (g_hash_table_lookup (registry->priv->monitor_table, file) == NULL) {
+ GFileMonitor *monitor;
+ GError *error;
+
+ error = NULL;
+ monitor = g_file_monitor (file,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ &error);
+
+ if (monitor != NULL) {
+ g_signal_connect (monitor, "changed",
+ G_CALLBACK (_monitor_changed_cb),
+ registry);
+
+ g_hash_table_replace (registry->priv->monitor_table,
+ g_object_ref (file),
+ monitor);
+ } else {
+ g_warning ("Can't monitor directory %s: %s",
+ path->path,
+ error->message);
+ g_error_free (error);
+ }
+ }
+ g_object_unref (file);
+ }
+ g_list_free (observed_paths);
+}
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/* vim:set et sts=4: */
+/* bus - The Input Bus
+ * Copyright (C) 2013 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#if !defined (__IBUS_H_INSIDE__) && !defined (IBUS_COMPILATION)
+#error "Only <ibus.h> can be included directly"
+#endif
+
+#ifndef __IBUS_REGISTRY_H_
+#define __IBUS_REGISTRY_H_
+
+/**
+ * SECTION: ibusregistry
+ * @short_description: Registry cache handling.
+ * @title: IBusRegistry
+ * @stability: Stable
+ *
+ * An #IBusRegistry loads IBus component files and generates the cache files.
+ *
+ * see_also: #IBusComponent
+ */
+
+#include "ibuscomponent.h"
+
+/*
+ * Type macros.
+ */
+
+/* define GOBJECT macros */
+#define IBUS_TYPE_REGISTRY \
+ (ibus_registry_get_type ())
+#define IBUS_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_REGISTRY, IBusRegistry))
+#define IBUS_REGISTRY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_REGISTRY, IBusRegistryClass))
+#define IBUS_IS_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_REGISTRY))
+#define IBUS_IS_REGISTRY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_REGISTRY))
+#define IBUS_REGISTRY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_REGISTRY, IBusRegistryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _IBusRegistry IBusRegistry;
+typedef struct _IBusRegistryPrivate IBusRegistryPrivate;
+typedef struct _IBusRegistryClass IBusRegistryClass;
+
+/**
+ * IBusRegistry:
+ *
+ * Registry cache handling.
+ * You can load the registry from compose files or a cache file.
+ */
+struct _IBusRegistry {
+ /* instance members */
+ /*< private >*/
+ IBusObject parent;
+ IBusRegistryPrivate *priv;
+};
+
+struct _IBusRegistryClass {
+ /* class members */
+ /*< private >*/
+ IBusObjectClass parent;
+};
+
+GType ibus_registry_get_type (void);
+
+/**
+ * ibus_registry_new:
+ * @returns: A newly allocated #IBusRegistry.
+ *
+ * New a #IBusRegistry
+ */
+IBusRegistry *ibus_registry_new (void);
+
+/**
+ * ibus_registry_load:
+ * @registry: An #IBusRegistry.
+ *
+ * Read all XML files in a IBus component directory (typically
+ * /usr/share/ibus/component/ *.xml) and update the registry object.
+ * IBUS_COMPONENT_PATH environment valuable is also available for
+ * the custom component directories, whose delimiter is ':'.
+ */
+void ibus_registry_load (IBusRegistry *registry);
+
+/**
+ * ibus_registry_load_in_dir:
+ * @registry: An #IBusRegistry.
+ * @dirname: IBus component directory which includes XML files.
+ *
+ * Read all XML files in @dirname, create a #IBusComponent object for each file,
+ * and add the component objects to the registry.
+ * If @dirname is "/usr/share/ibus/component", this API and
+ * ibus_registry_load() are same.
+ */
+void ibus_registry_load_in_dir (IBusRegistry *registry,
+ const gchar *dirname);
+
+/**
+ * ibus_registry_load_cache:
+ * @registry: An #IBusRegistry.
+ * @is_user: %TRUE if the registry cache is loaded in the user directory.
+ * @returns: %TRUE if the cache exists and is loaded successfully,
+ * %FALSE otherwise.
+ *
+ * Load the user or system registry cache.
+ */
+gboolean ibus_registry_load_cache (IBusRegistry *registry,
+ gboolean is_user);
+
+/**
+ * ibus_registry_load_cache_file:
+ * @registry: An #IBusRegistry.
+ * @filename: The file path of the registry cache
+ * @returns: %TRUE if the cache exists and is loaded successfully,
+ * %FALSE otherwise.
+ *
+ * Load the registry cache @filename.
+ */
+gboolean ibus_registry_load_cache_file (IBusRegistry *registry,
+ const gchar *filename);
+
+/**
+ * ibus_registry_save_cache:
+ * @registry: An #IBusRegistry.
+ * @is_user: %TRUE if the registry cache is saved in the user directory.
+ * @returns: %TRUE if the cache is saved successfully, %FALSE otherwise.
+ *
+ * Save the registry in a user directory or system directory.
+ */
+gboolean ibus_registry_save_cache (IBusRegistry *registry,
+ gboolean is_user);
+
+/**
+ * ibus_registry_save_cache_file:
+ * @registry: An #IBusRegistry.
+ * @filename: The file path of the registry cache
+ * @returns: %TRUE if the cache is saved successfully, %FALSE otherwise.
+ *
+ * Save the registry cache @filename.
+ */
+gboolean ibus_registry_save_cache_file (IBusRegistry *registry,
+ const gchar *filename);
+
+/**
+ * ibus_registry_output:
+ * @registry: An #IBusRegistry.
+ * @output: GString that holds the result.
+ * @indent: level of indent.
+ *
+ * Output #IBusRegistry as an XML-formatted string.
+ * The output string can be then shown on the screen or written to file.
+ */
+void ibus_registry_output (IBusRegistry *registry,
+ GString *output,
+ int indent);
+
+/**
+ * ibus_registry_check_modification:
+ * @registry: An #IBusRegistry.
+ * @returns: %TRUE if mtime is changed; %FALSE otherwise.
+ *
+ * Check if the registry is updated.
+ */
+gboolean ibus_registry_check_modification
+ (IBusRegistry *registry);
+
+/**
+ * ibus_registry_get_components:
+ * @registry: An #IBusRegistry.
+ * @returns: (transfer container) (element-type IBusComponent):
+ * a list of #IBusComponent objects.
+ * The caller has to call g_list_free() for the returned list.
+ *
+ * List components.
+ */
+GList *ibus_registry_get_components (IBusRegistry *registry);
+
+/**
+ * ibus_registry_get_observed_paths:
+ * @registry: An #IBusRegistry.
+ * @returns: (transfer container) (element-type IBusObservedPath):
+ * a list of #IBusObservedPath objects.
+ * The caller has to call g_list_free() for the returned list.
+ *
+ * List observed paths.
+ */
+GList *ibus_registry_get_observed_paths
+ (IBusRegistry *registry);
+
+/**
+ * ibus_registry_start_monitor_changes:
+ * @registry: An #IBusRegistry.
+ *
+ * Start to monitor observed paths.
+ */
+void ibus_registry_start_monitor_changes
+ (IBusRegistry *registry);
+
+G_END_DECLS
+#endif
#
# ibus - The Input Bus
#
-# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com>
-# Copyright (c) 2007-2010 Red Hat, Inc.
+# Copyright (c) 2007-2013 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
$(NULL)
noinst_PROGRAMS = $(TESTS)
-TESTS = \
- ibus-bus \
- ibus-config \
- ibus-configservice\
- ibus-factory \
- ibus-inputcontext \
- ibus-inputcontext-create \
- ibus-keynames \
- ibus-serializable \
- ibus-share \
- ibus-util \
+TESTS = \
+ ibus-bus \
+ ibus-config \
+ ibus-configservice \
+ ibus-factory \
+ ibus-inputcontext \
+ ibus-inputcontext-create \
+ ibus-keynames \
+ ibus-registry \
+ ibus-serializable \
+ ibus-share \
+ ibus-util \
$(NULL)
if ENABLE_ENGINE
ibus_keynames_SOURCES = ibus-keynames.c
ibus_keynames_LDADD = $(prog_ldadd)
+ibus_registry_SOURCES = ibus-registry.c
+ibus_registry_LDADD = $(prog_ldadd)
+
ibus_serializable_SOURCES = ibus-serializable.c
ibus_serializable_LDADD = $(prog_ldadd)
--- /dev/null
+#include <ibus.h>
+
+int main()
+{
+#if !GLIB_CHECK_VERSION(2,35,0)
+ g_type_init ();
+#endif
+ IBusRegistry *registry = ibus_registry_new ();
+ g_object_unref (registry);
+ return 0;
+}
\fBversion\fR
Show the ibus version.
.TP
+\fBread\-cache\fR [\fB\-\-system|\-\-file=FILE\fR]
+Show the content of the user registry cache if
+.B \-\-system
+is not given.
+Show the content of the system registry cache if
+.B \-\-system
+is given.
+Show the content of the custom registry cache
+.B FILE
+if
+.B \-\-file=FILE
+is given.
+.TP
+\fBwrite\-cache\fR [\fB\-\-system|\-\-file=FILE\fR]
+Save the user registry cache if
+.B \-\-system
+is not given.
+Save the system registry cache if
+.B \-\-system
+is given.
+Save the custom registry cache
+.B FILE
+if
+.B \-\-file=FILE
+is given.
+IBUS_COMPONENT_PATH environment valuable is also available for
+the custom component directories, whose delimiter is ':'.
+.TP
\fBwatch\fR
Under construction.
+.TP
.SH BUGS
If you find a bug, please report it at http://code.google.com/p/ibus/issues/list.
*
* ibus - The Input Bus
*
- * Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright(c) 2013 Peng Huang <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
*/
bool name_only = false;
+/* system() exists as a public API. */
+bool is_system = false;
+string cache_file = null;
class EngineList {
public IBus.EngineDesc[] data = {};
{ null }
};
- var option = new OptionContext(_("command [OPTIONS]"));
- option.add_main_entries(options, "ibus");
+ var option = new OptionContext();
+ option.add_main_entries(options, Config.GETTEXT_PACKAGE);
try {
option.parse(ref argv);
return Posix.EXIT_SUCCESS;
}
+int read_cache (string[] argv) {
+ const OptionEntry[] options = {
+ { "system", 0, 0, OptionArg.NONE, out is_system,
+ N_("Read the system registry cache."), null },
+ { "file", 0, 0, OptionArg.STRING, out cache_file,
+ N_("Read the registry cache FILE."), "FILE" },
+ { null }
+ };
+
+ var option = new OptionContext();
+ option.add_main_entries(options, Config.GETTEXT_PACKAGE);
+
+ try {
+ option.parse(ref argv);
+ } catch (OptionError e) {
+ stderr.printf("%s\n", e.message);
+ return Posix.EXIT_FAILURE;
+ }
+
+ var registry = new IBus.Registry();
+
+ if (cache_file != null) {
+ if (!registry.load_cache_file(cache_file)) {
+ stderr.printf(_("The registry cache is invalid.\n"));
+ return Posix.EXIT_FAILURE;
+ }
+ } else {
+ if (!registry.load_cache(!is_system)) {
+ stderr.printf(_("The registry cache is invalid.\n"));
+ return Posix.EXIT_FAILURE;
+ }
+ }
+
+ var output = new GLib.StringBuilder();
+ registry.output(output, 1);
+
+ print ("%s\n", output.str);
+ return Posix.EXIT_SUCCESS;
+}
+
+int write_cache (string[] argv) {
+ const OptionEntry[] options = {
+ { "system", 0, 0, OptionArg.NONE, out is_system,
+ N_("Write the system registry cache."), null },
+ { "file", 0, 0, OptionArg.STRING, out cache_file,
+ N_("Write the registry cache FILE."),
+ "FILE" },
+ { null }
+ };
+
+ var option = new OptionContext();
+ option.add_main_entries(options, Config.GETTEXT_PACKAGE);
+
+ try {
+ option.parse(ref argv);
+ } catch (OptionError e) {
+ stderr.printf("%s\n", e.message);
+ return Posix.EXIT_FAILURE;
+ }
+
+ var registry = new IBus.Registry();
+ registry.load();
+
+ if (cache_file != null) {
+ return registry.save_cache_file(cache_file) ?
+ Posix.EXIT_SUCCESS : Posix.EXIT_FAILURE;
+ }
+
+ return registry.save_cache(!is_system) ?
+ Posix.EXIT_SUCCESS : Posix.EXIT_FAILURE;
+}
+
int print_help(string[] argv) {
print_usage(stdout);
return Posix.EXIT_SUCCESS;
{ "watch", message_watch },
{ "restart", restart_daemon },
{ "version", print_version },
+ { "read-cache", read_cache },
+ { "write-cache", write_cache },
{ "help", print_help }
};
}
public int main(string[] argv) {
+ GLib.Intl.setlocale(GLib.LocaleCategory.ALL, "");
GLib.Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.GLIB_LOCALE_DIR);
GLib.Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8");
}
string[] new_argv = argv[1:argv.length];
+ new_argv[0] = "%s %s".printf(program_name, new_argv[0]);
for (int i = 0; i < commands.length; i++) {
if (commands[i].name == argv[1])
return commands[i].entry(new_argv);