diff options
author | glasseyes <dglassey@gmail.com> | 2018-10-25 13:48:49 +0700 |
---|---|---|
committer | glasseyes <dglassey@gmail.com> | 2018-10-25 13:48:49 +0700 |
commit | 652c6120e2b1b616b32b917453df52fd1d3afd35 (patch) | |
tree | 3589089e5bb71def90802be6aed0d3344d2a1ed4 /src | |
parent | d1948ed24d149a270dd00788a2c4a017a51cc88c (diff) |
New upstream version 10.99.33
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/Makefile.in | 49 | ||||
-rw-r--r-- | src/engine.c | 114 | ||||
-rw-r--r-- | src/keyman-service.c | 379 | ||||
-rw-r--r-- | src/keyman-service.h | 69 | ||||
-rw-r--r-- | src/kmfl.xml.in | 4 | ||||
-rw-r--r-- | src/kmfl.xml.in.in | 2 | ||||
-rw-r--r-- | src/kmflutil.c | 219 | ||||
-rw-r--r-- | src/kmflutil.h | 40 | ||||
-rw-r--r-- | src/main.c | 5 |
10 files changed, 767 insertions, 116 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index df1e959..d52a1aa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,6 +53,8 @@ ibus_engine_kmfl_SOURCES = \ main.c \ engine.c \ engine.h \ + keyman-service.c \ + keyman-service.h \ $(NULL) ibus_engine_kmfl_CFLAGS = \ @IBUS_CFLAGS@ \ diff --git a/src/Makefile.in b/src/Makefile.in index 96184e2..eb8f11e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -36,7 +36,17 @@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -103,9 +113,6 @@ check_PROGRAMS = test-kmfl$(EXEEXT) TESTS = $(check_PROGRAMS) libexec_PROGRAMS = ibus-engine-kmfl$(EXEEXT) subdir = src -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(srcdir)/kmfl.xml.in.in $(top_srcdir)/depcomp \ - $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ @@ -117,6 +124,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = kmfl.xml.in @@ -126,7 +134,8 @@ am__installdirs = "$(DESTDIR)$(libexecdir)" \ PROGRAMS = $(libexec_PROGRAMS) am_ibus_engine_kmfl_OBJECTS = ibus_engine_kmfl-kmflutil.$(OBJEXT) \ ibus_engine_kmfl-main.$(OBJEXT) \ - ibus_engine_kmfl-engine.$(OBJEXT) + ibus_engine_kmfl-engine.$(OBJEXT) \ + ibus_engine_kmfl-keyman-service.$(OBJEXT) ibus_engine_kmfl_OBJECTS = $(am_ibus_engine_kmfl_OBJECTS) ibus_engine_kmfl_LDADD = $(LDADD) AM_V_lt = $(am__v_lt_@AM_V@) @@ -408,6 +417,8 @@ TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/kmfl.xml.in.in \ + $(top_srcdir)/depcomp $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -464,6 +475,7 @@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ @@ -543,6 +555,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -576,6 +589,8 @@ ibus_engine_kmfl_SOURCES = \ main.c \ engine.c \ engine.h \ + keyman-service.c \ + keyman-service.h \ $(NULL) ibus_engine_kmfl_CFLAGS = \ @@ -617,7 +632,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -711,6 +725,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_kmfl-engine.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_kmfl-keyman-service.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_kmfl-kmflutil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_kmfl-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_kmfl-kmflutil.Po@am__quote@ @@ -778,6 +793,20 @@ ibus_engine_kmfl-engine.obj: engine.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_kmfl_CFLAGS) $(CFLAGS) -c -o ibus_engine_kmfl-engine.obj `if test -f 'engine.c'; then $(CYGPATH_W) 'engine.c'; else $(CYGPATH_W) '$(srcdir)/engine.c'; fi` +ibus_engine_kmfl-keyman-service.o: keyman-service.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_kmfl_CFLAGS) $(CFLAGS) -MT ibus_engine_kmfl-keyman-service.o -MD -MP -MF $(DEPDIR)/ibus_engine_kmfl-keyman-service.Tpo -c -o ibus_engine_kmfl-keyman-service.o `test -f 'keyman-service.c' || echo '$(srcdir)/'`keyman-service.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_kmfl-keyman-service.Tpo $(DEPDIR)/ibus_engine_kmfl-keyman-service.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keyman-service.c' object='ibus_engine_kmfl-keyman-service.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_kmfl_CFLAGS) $(CFLAGS) -c -o ibus_engine_kmfl-keyman-service.o `test -f 'keyman-service.c' || echo '$(srcdir)/'`keyman-service.c + +ibus_engine_kmfl-keyman-service.obj: keyman-service.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_kmfl_CFLAGS) $(CFLAGS) -MT ibus_engine_kmfl-keyman-service.obj -MD -MP -MF $(DEPDIR)/ibus_engine_kmfl-keyman-service.Tpo -c -o ibus_engine_kmfl-keyman-service.obj `if test -f 'keyman-service.c'; then $(CYGPATH_W) 'keyman-service.c'; else $(CYGPATH_W) '$(srcdir)/keyman-service.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_kmfl-keyman-service.Tpo $(DEPDIR)/ibus_engine_kmfl-keyman-service.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keyman-service.c' object='ibus_engine_kmfl-keyman-service.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_kmfl_CFLAGS) $(CFLAGS) -c -o ibus_engine_kmfl-keyman-service.obj `if test -f 'keyman-service.c'; then $(CYGPATH_W) 'keyman-service.c'; else $(CYGPATH_W) '$(srcdir)/keyman-service.c'; fi` + test_kmfl-kmflutil.o: kmflutil.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_kmfl_CFLAGS) $(CFLAGS) -MT test_kmfl-kmflutil.o -MD -MP -MF $(DEPDIR)/test_kmfl-kmflutil.Tpo -c -o test_kmfl-kmflutil.o `test -f 'kmflutil.c' || echo '$(srcdir)/'`kmflutil.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_kmfl-kmflutil.Tpo $(DEPDIR)/test_kmfl-kmflutil.Po @@ -901,7 +930,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ - else \ + elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ @@ -1196,6 +1225,8 @@ uninstall-am: uninstall-componentDATA uninstall-libexecPROGRAMS pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-componentDATA uninstall-libexecPROGRAMS +.PRECIOUS: Makefile + kmfl.xml: kmfl.xml.in ( \ diff --git a/src/engine.c b/src/engine.c index b7e0275..f7e01b7 100644 --- a/src/engine.c +++ b/src/engine.c @@ -29,6 +29,7 @@ #include <X11/keysym.h> #include "kmflutil.h" +#include "keyman-service.h" #include "engine.h" typedef struct _IBusKMFLEngine IBusKMFLEngine; @@ -100,93 +101,6 @@ static IBusEngineClass *parent_class = NULL; static GHashTable *im_table = NULL; -void output_string(void *contrack, char *ptr) { - KInputContext * ic = (KInputContext *)contrack; - g_debug("DAR: output_string - ic->cmds=%p", ic->cmds); - if (ptr) { - Cmd * cmd = g_new(Cmd, 1); - cmd->opcode=OUTPUT_STRING; - cmd->cmdarg=g_strdup(ptr); - ic->cmds = g_list_append(ic->cmds, cmd); - } -} - -void erase_char(void *contrack) { - KInputContext * ic = (KInputContext *)contrack; - g_debug("DAR: erase_char - ic->cmds=%p", ic->cmds); - Cmd * cmd = g_new(Cmd, 1); - cmd->opcode = ERASE_CHAR; - cmd->cmdarg=NULL; - ic->cmds = g_list_append(ic->cmds, cmd); -} - -void output_char(void *contrack, unsigned char byte) { - if (byte == 8) { - erase_char(contrack); - } else { - char s[2]; - s[0] = byte; - s[1] = '\0'; - output_string(contrack, s); - } -} - -void forward_keyevent(void *contrack, unsigned int key, unsigned int state) -{ - -} - -void output_beep(void *contrack) { - KInputContext * ic = (KInputContext *)contrack; - Cmd * cmd = g_new(Cmd, 1); - cmd->opcode = OUTPUT_BEEP; - cmd->cmdarg=NULL; - ic->cmds = g_list_append(ic->cmds, cmd); -} - -/* - * Create an input context - */ -KInputContext * -kmfl_create_ic(KInputMethod *im) -{ - KInputContext * ic; - g_debug("DAR: kmfl_create_ic"); - ic = g_new(KInputContext, 1); - ic->cmds = NULL; - ic->p_kmsi=kmfl_make_keyboard_instance(ic); - kmfl_attach_keyboard(ic->p_kmsi, im->keyboard_number); - - return ic; -} - - -/* - * Destroy an input context - */ -void -kmfl_destroy_ic(KInputContext *ic) -{ - GList * p; - g_debug("DAR: kmfl_destroy_ic"); - kmfl_detach_keyboard(ic->p_kmsi); - kmfl_delete_keyboard_instance(ic->p_kmsi); - - if (ic->cmds) { - for (p=ic->cmds; p != NULL; p = p->next) { - Cmd * cmd = (Cmd *)p->data; - if (cmd) { - if (cmd->cmdarg) - g_free(cmd->cmdarg); - g_free(cmd); - } - } - g_list_free(ic->cmds); - ic->cmds=NULL; - } - -} - GType ibus_kmfl_engine_get_type (void) { @@ -283,6 +197,7 @@ ibus_kmfl_engine_constructor (GType type, engine_name = ibus_engine_get_name ((IBusEngine *) kmfl); g_assert (engine_name); + g_message("DAR: ibus_kmfl_engine_constructor %s", engine_name); if (im_table == NULL) { im_table = g_hash_table_new_full (g_str_hash, @@ -318,10 +233,11 @@ static void ibus_kmfl_engine_destroy (IBusKMFLEngine *kmfl) { const gchar *engine_name; - g_debug("DAR: ibus_kmfl_engine_destroy"); + g_debug("DAR: ibus_kmfl_engine_destroy"); engine_name = ibus_engine_get_name ((IBusEngine *) kmfl); g_assert (engine_name); + g_message("DAR: ibus_kmfl_engine_destroy %s", engine_name); if (kmfl->prop_list) { g_debug("DAR: unref kmfl->prop_list"); @@ -489,17 +405,39 @@ ibus_kmfl_engine_reset (IBusEngine *engine) static void ibus_kmfl_engine_enable (IBusEngine *engine) { + const gchar *engine_name; IBusKMFLEngine *kmfl = (IBusKMFLEngine *) engine; + KInputMethod *im; + engine_name = ibus_engine_get_name (engine); + g_assert (engine_name); + g_message("WDG: ibus_kmfl_engine_enable %s", engine_name); + im = (KInputMethod *) g_hash_table_lookup (im_table, engine_name); + // own dbus name com.Keyman + // expose properties LDMLFile and Name + KeymanService *service = km_service_get_default(); + //const gchar *ldmlfile = ""; + km_service_set_ldmlfile (service, im->keyboard_ldmlfile); + km_service_set_name (service, im->keyboard_name); parent_class->enable (engine); } static void ibus_kmfl_engine_disable (IBusEngine *engine) { + const gchar *engine_name; IBusKMFLEngine *kmfl = (IBusKMFLEngine *) engine; + engine_name = ibus_engine_get_name (engine); + g_assert (engine_name); + g_message("WDG: ibus_kmfl_engine_disable %s", engine_name); ibus_kmfl_engine_focus_out (engine); + // stop owning dbus name com.Keyman + KeymanService *service = km_service_get_default(); + km_service_set_ldmlfile (service, ""); + km_service_set_name (service, "None"); + // g_clear_object(&service); + parent_class->disable (engine); } diff --git a/src/keyman-service.c b/src/keyman-service.c new file mode 100644 index 0000000..c768430 --- /dev/null +++ b/src/keyman-service.c @@ -0,0 +1,379 @@ +/* vim:set et sts=4: */ + +/* + * KMFL Input Method for IBUS (The Input Bus) + * + * Copyright (C) 2018 SIL International + * + * This library 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 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + + /* + This file is based on work from Mousetweaks + Copyright © 2007-2010 Gerd Kohlberger <gerdko gmail com> +*/ + +#include <gio/gio.h> + +#include "keyman-service.h" + +struct _KeymanServicePrivate +{ + guint owner_id; + GDBusNodeInfo *ispec; + + gchar * name; + gchar * ldmlfile; +}; + +enum +{ + PROP_0, + PROP_NAME, + PROP_LDMLFILE +}; + +static const gchar introspection_xml[] = + "<node>" + " <interface name='com.Keyman'>" + " <property type='s' name='LDMLFile' access='read'/>" + " <property type='s' name='Name' access='read'/>" + " </interface>" + "</node>"; + +static void km_service_bus_acquired (GDBusConnection *connection, + const gchar *name, + gpointer data); + +G_DEFINE_TYPE (KeymanService, km_service, G_TYPE_OBJECT) + +static void +km_service_init (KeymanService *service) +{ + KeymanServicePrivate *priv; + GError *error = NULL; + + g_message("WDG: km_service_init"); + + service->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (service, + KM_TYPE_SERVICE, + KeymanServicePrivate); + + priv->name = g_strdup ("None"); + priv->ldmlfile = g_strdup (""); + priv->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + KEYMAN_DBUS_NAME, + G_BUS_NAME_OWNER_FLAGS_NONE, + km_service_bus_acquired, + NULL, NULL, + service, NULL); + priv->ispec = g_dbus_node_info_new_for_xml (introspection_xml, &error); + if (error) + { + g_warning ("%s\n", error->message); + g_error_free (error); + } +} + +static void +km_service_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + KeymanService *service = KM_SERVICE (object); + + switch (prop_id) + { + case PROP_NAME: + if (service->priv->name) + { + g_free(service->priv->name); + } + service->priv->name = g_value_dup_string (value); + break; + case PROP_LDMLFILE: + if (service->priv->ldmlfile) + { + g_free(service->priv->ldmlfile); + } + service->priv->ldmlfile = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +km_service_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + KeymanService *service = KM_SERVICE (object); + + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, service->priv->name); + break; + case PROP_LDMLFILE: + g_value_set_string (value, service->priv->ldmlfile); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +km_service_dispose (GObject *object) +{ + g_message("WDG: km_service_dispose"); + KeymanServicePrivate *priv = KM_SERVICE (object)->priv; + + if (priv->owner_id) + { + g_bus_unown_name (priv->owner_id); + priv->owner_id = 0; + } + + if (priv->ispec) + { + g_dbus_node_info_unref (priv->ispec); + priv->ispec = NULL; + } + + if (priv->name) + { + g_free(priv->name); + } + + if (priv->ldmlfile) + { + g_free(priv->ldmlfile); + } + + G_OBJECT_CLASS (km_service_parent_class)->dispose (object); +} + +static void +km_service_class_init (KeymanServiceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = km_service_get_property; + object_class->set_property = km_service_set_property; + object_class->dispose = km_service_dispose; + + g_object_class_install_property (object_class, + PROP_NAME, + g_param_spec_string ("name", + "Name", + "Name of the currently active Keyman keyboard", + "None", + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_LDMLFILE, + g_param_spec_string ("ldmlfile", + "LDML file", + "On screen keyboard file for the currently active Keyman keyboard", + "", + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_type_class_add_private (klass, sizeof (KeymanServicePrivate)); +} + +static GVariant * +handle_get_property (GDBusConnection *connection, + const gchar *sender, + const gchar *path, + const gchar *interface_name, + const gchar *property, + GError **error, + KeymanService *service) +{ + GVariant *ret = NULL; + + if (g_strcmp0 (property, "Name") == 0) + { + ret = g_variant_new_string (service->priv->name); + } + else if (g_strcmp0 (property, "LDMLFile") == 0) + { + ret = g_variant_new_string (service->priv->ldmlfile); + } + return ret; +} + +static gboolean +handle_set_property (GDBusConnection *connection, + const gchar *sender, + const gchar *path, + const gchar *interface, + const gchar *property, + GVariant *value, + GError **error, + KeymanService *service) +{ + gsize sz; + if (g_strcmp0 (property, "Name") == 0) + { + km_service_set_name (service, g_variant_dup_string (value, &sz)); + } + else if (g_strcmp0 (property, "LDMLFile") == 0) + { + km_service_set_ldmlfile (service, g_variant_dup_string (value, &sz)); + } + return TRUE; +} + +static const GDBusInterfaceVTable interface_vtable = +{ + (GDBusInterfaceMethodCallFunc) NULL, + (GDBusInterfaceGetPropertyFunc) handle_get_property, + (GDBusInterfaceSetPropertyFunc) handle_set_property +}; + +static void +emit_property_changed (GObject *object, + GParamSpec *pspec, + GDBusConnection *connection) +{ + KeymanService *service = KM_SERVICE (object); + GError *error = NULL; + GVariantBuilder builder, inv_builder; + GVariant *prop_v; + + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_init (&inv_builder, G_VARIANT_TYPE ("as")); + + if (g_strcmp0 (pspec->name, "name") == 0) + { + g_variant_builder_add (&builder, "{sv}", "Name", + g_variant_new_string (service->priv->name)); + } + else if (g_strcmp0 (pspec->name, "ldmlfile") == 0) + { + g_variant_builder_add (&builder, "{sv}", "LDMLFile", + g_variant_new_string (service->priv->ldmlfile)); + } + + prop_v = g_variant_new ("(sa{sv}as)", + KEYMAN_DBUS_IFACE, + &builder, &inv_builder); + + if (!g_dbus_connection_emit_signal (connection, NULL, + KEYMAN_DBUS_PATH, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + prop_v, &error)) + { + g_warning ("%s\n", error->message); + g_error_free (error); + } +} + +static void +km_service_bus_acquired (GDBusConnection *connection, + const gchar *name, + gpointer data) +{ + KeymanService *service = data; + + if (service->priv->ispec) + { + GError *error = NULL; + + g_dbus_connection_register_object (connection, + KEYMAN_DBUS_PATH, + service->priv->ispec->interfaces[0], + &interface_vtable, + service, NULL, &error); + if (error) + { + g_warning ("%s", error->message); + g_error_free (error); + } + + g_signal_connect (service, "notify", + G_CALLBACK (emit_property_changed), connection); + } +} + +KeymanService * +km_service_get_default (void) +{ + static KeymanService *service = NULL; + + // if (service) + // { + // g_free(service); + // service = g_object_new (KM_TYPE_SERVICE, NULL); + // g_object_add_weak_pointer (G_OBJECT (service), (gpointer *) &service); + // } + if (!service) + { + service = g_object_new (KM_TYPE_SERVICE, NULL); + g_object_add_weak_pointer (G_OBJECT (service), (gpointer *) &service); + } + return service; +} + +void +km_service_set_name (KeymanService *service, + const gchar *name) +{ + g_return_if_fail (KM_IS_SERVICE (service)); + + if (g_strcmp0(name,service->priv->name) != 0) + { + g_free(service->priv->name); + service->priv->name = g_strdup(name); + g_object_notify (G_OBJECT (service), "name"); + } +} + +// const gchar * +// km_service_get_name (KeymanService *service) +// { +// g_return_val_if_fail (KM_IS_SERVICE (service), -1); + +// return service->priv->name; +// } + +void +km_service_set_ldmlfile (KeymanService *service, + const gchar *xml) +{ + g_return_if_fail (KM_IS_SERVICE (service)); + + if (g_strcmp0(xml,service->priv->ldmlfile) != 0) + { + g_free(service->priv->ldmlfile); + service->priv->ldmlfile = g_strdup(xml); + g_object_notify (G_OBJECT (service), "ldmlfile"); + } +} + +// const gchar * +// km_service_get_ldmlfile (KeymanService *service) +// { +// g_return_val_if_fail (KM_IS_SERVICE (service), -1); + +// return service->priv->ldmlfile; +// } diff --git a/src/keyman-service.h b/src/keyman-service.h new file mode 100644 index 0000000..0ce5237 --- /dev/null +++ b/src/keyman-service.h @@ -0,0 +1,69 @@ +/* vim:set et sts=4: */ + +/* + * KMFL Input Method for IBUS (The Input Bus) + * + * Copyright (C) 2018 SIL International + * + * This library 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 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + + /* + This file is based on work from Mousetweaks + Copyright © 2007-2010 Gerd Kohlberger <gerdko gmail com> +*/ + +#ifndef __KM_SERVICE_H__ +#define __KM_SERVICE_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define KEYMAN_DBUS_NAME "com.Keyman" +#define KEYMAN_DBUS_IFACE "com.Keyman" +#define KEYMAN_DBUS_PATH "/com/Keyman/IBus" + +#define KM_TYPE_SERVICE (km_service_get_type ()) +#define KM_SERVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), KM_TYPE_SERVICE, KeymanService)) +#define KM_IS_SERVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), KM_TYPE_SERVICE)) + +typedef GObjectClass KeymanServiceClass; +typedef struct _KeymanService KeymanService; +typedef struct _KeymanServicePrivate KeymanServicePrivate; + +struct _KeymanService +{ + GObject parent; + KeymanServicePrivate *priv; +}; + +GType km_service_get_type (void) G_GNUC_CONST; + +KeymanService * km_service_get_default (void); + +// const gchar * km_service_get_ldmlfile (KeymanService *service); +void km_service_set_ldmlfile (KeymanService *service, + const gchar *xml); + +// const gchar * km_service_get_name (KeymanService *service); +void km_service_set_name (KeymanService *service, + const gchar *name); + + +G_END_DECLS + +#endif /* __KM_SERVICE_H__ */ diff --git a/src/kmfl.xml.in b/src/kmfl.xml.in index 78c32a2..d284c37 100644 --- a/src/kmfl.xml.in +++ b/src/kmfl.xml.in @@ -4,7 +4,7 @@ <name>org.freedesktop.IBus.KMFL</name> <description>KMFL Component</description> <exec>${libexecdir}/ibus-engine-kmfl --ibus</exec> - <version>1.0.8</version> + <version>10.99.33</version> <author>Doug Rintoul <doug_rintoul@sil.org></author> <license>GPL</license> <homepage>http://kmfl.sourceforge.net</homepage> @@ -12,6 +12,8 @@ <observed-paths> <path>/usr/share/kmfl/</path> <path>~/.kmfl/</path> + <path>/usr/local/share/keyman/</path> + <path>~/.local/share/keyman/</path> </observed-paths> <engines exec=\"${libexecdir}/ibus-engine-kmfl --xml\" /> </component> diff --git a/src/kmfl.xml.in.in b/src/kmfl.xml.in.in index 70afebc..b42c001 100644 --- a/src/kmfl.xml.in.in +++ b/src/kmfl.xml.in.in @@ -12,6 +12,8 @@ <observed-paths> <path>/usr/share/kmfl/</path> <path>~/.kmfl/</path> + <path>/usr/local/share/keyman/</path> + <path>~/.local/share/keyman/</path> </observed-paths> <engines exec=\"${libexecdir}/ibus-engine-kmfl --xml\" /> </component> diff --git a/src/kmflutil.c b/src/kmflutil.c index 516df2e..983ce98 100644 --- a/src/kmflutil.c +++ b/src/kmflutil.c @@ -3,14 +3,42 @@ /* * KMFL Input Method for IBUS (The Input Bus) * - * Copyright (C) 2009 SIL International + * Copyright (C) 2009-2018 SIL International * - * This library is free software; you can redistribute it and/or + * kmflutil is dual licensed under the MIT or GPL licenses as described below. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * MIT license + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * OR + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * 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 library is distributed in the hope that it will be useful, + * 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. @@ -21,6 +49,8 @@ * */ + + #include <stdlib.h> #include <dirent.h> #include <sys/stat.h> @@ -42,10 +72,9 @@ static gchar * get_dirname(const gchar * path) } } -GList * kmfl_get_keyboard_list( const gchar * path) +GList * kmfl_get_keyboard_fromdir( GList *keyboard_list, const gchar * path) { - GList * keyboard_list=NULL; - +// g_message("KMFL: getting from dir: %s", path); DIR *dir = opendir(path); if (dir != NULL) { @@ -55,14 +84,24 @@ GList * kmfl_get_keyboard_list( const gchar * path) gchar * absfn = g_strdup_printf("%s/%s", path, file->d_name); stat(absfn, &filestat); + if (S_ISDIR(filestat.st_mode)) + { + if(strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0) + keyboard_list = kmfl_get_keyboard_fromdir(keyboard_list, absfn); + g_free(absfn); + } // Only .kmfl and .kmn extensions are valid keyboard files - if (S_ISREG(filestat.st_mode) + else if (S_ISREG(filestat.st_mode) && ((g_str_has_suffix(absfn, ".kmfl") && kmfl_check_keyboard(absfn) == 0) || g_str_has_suffix(absfn, ".kmn"))) { keyboard_list=g_list_append(keyboard_list, absfn); } + else + { + g_free(absfn); + } file = readdir(dir); } @@ -71,17 +110,24 @@ GList * kmfl_get_keyboard_list( const gchar * path) return keyboard_list; } +GList * kmfl_get_keyboard_list( const gchar * path) +{ + GList * keyboard_list=NULL; + keyboard_list = kmfl_get_keyboard_fromdir(keyboard_list, path); + return keyboard_list; +} + gchar * kmfl_get_icon_file(KInputMethod * im) { const char * icon_file = kmfl_icon_file(im->keyboard_number); gchar * full_path_to_icon_file=NULL; struct stat filestat; - char * valid_extensions[]= {"", ".png", ".bmp", ".jpg", ".ico", NULL}; + char * valid_extensions[]= {"", ".png", ".bmp", ".jpg", NULL}; int valid_extension_index; if (strlen(icon_file) > 0) { for (valid_extension_index=0; valid_extensions[valid_extension_index] != NULL; valid_extension_index++) { - full_path_to_icon_file=g_strdup_printf("%s/icons/%s%s", get_dirname(im->keyboard_filename), icon_file, valid_extensions[valid_extension_index]); + full_path_to_icon_file=g_strdup_printf("%s/%s%s", get_dirname(im->keyboard_filename), icon_file, valid_extensions[valid_extension_index]); stat(full_path_to_icon_file, &filestat); @@ -100,11 +146,46 @@ gchar * kmfl_get_icon_file(KInputMethod * im) return full_path_to_icon_file; } +gchar * kmfl_get_ldml_file(KInputMethod * im) +{ + gchar * full_path_to_ldml_file=NULL, *p, *filename; + struct stat filestat; + + if(g_strcmp0(im->keyboard_visualkeyboard, "") == 0) + { + g_debug("WDG: no kvk(s) so no ldml file"); + return g_strdup(""); + } + p=rindex(im->keyboard_visualkeyboard,'.'); + if (p==NULL) + { + g_debug("WDG: couldn't find . in vk filename %s", im->keyboard_visualkeyboard); + return g_strdup(""); + } + if (strncmp(p, ".kvk", 4) != 0) // sometimes kmn have kvks as the "visual keyboard" + { + g_debug("WDG: visual keyboard is not a kvk. Filename: %s", im->keyboard_visualkeyboard); + return g_strdup(""); + } + filename = g_strndup(im->keyboard_visualkeyboard, p-(im->keyboard_visualkeyboard)); + full_path_to_ldml_file=g_strdup_printf("%s/%s.ldml", get_dirname(im->keyboard_filename), filename); + g_free(filename); + // don't forget to stat for the file before returning + stat(full_path_to_ldml_file, &filestat); + + if (!S_ISREG(filestat.st_mode)) { + g_debug("WDG: couldn't find ldml file %s", full_path_to_ldml_file); + g_free(full_path_to_ldml_file); + full_path_to_ldml_file=g_strdup(""); + } + return full_path_to_ldml_file; +} + void kmfl_get_keyboard_info(KInputMethod * im) { char buf[1024]; KMSI * p_kmsi; - + im->keyboard_name = g_strdup(kmfl_keyboard_name(im->keyboard_number)); p_kmsi = kmfl_make_keyboard_instance(NULL); kmfl_attach_keyboard(p_kmsi, im->keyboard_number); @@ -131,15 +212,24 @@ void kmfl_get_keyboard_info(KInputMethod * im) im->keyboard_license=g_strdup(""); *buf='\0'; + kmfl_get_header(p_kmsi,SS_VISUALKEYBOARD,buf,sizeof(buf) - 1); + im->keyboard_visualkeyboard=g_strdup(buf); + + *buf='\0'; + kmfl_get_header(p_kmsi,SS_KEYBOARDVERSION,buf,sizeof(buf) - 1); + im->keyboard_keyboardversion=g_strdup(buf); + + *buf='\0'; kmfl_get_header(p_kmsi,SS_LAYOUT,buf,sizeof(buf) - 1); if (*buf != '\0') im->keyboard_layout=g_strdup(buf); else im->keyboard_layout=g_strdup("us"); - + kmfl_detach_keyboard(p_kmsi); kmfl_delete_keyboard_instance(p_kmsi); im->keyboard_icon_filename = kmfl_get_icon_file(im); + im->keyboard_ldmlfile = kmfl_get_ldml_file(im); } void kmfl_free_keyboard_info(KInputMethod * im) @@ -154,6 +244,9 @@ void kmfl_free_keyboard_info(KInputMethod * im) g_free(im->keyboard_icon_filename); g_free(im->keyboard_layout); g_free(im->keyboard_license); + g_free(im->keyboard_visualkeyboard); + g_free(im->keyboard_keyboardversion); + g_free(im->keyboard_ldmlfile); } @@ -212,21 +305,29 @@ ibus_kmfl_list_engines (void) gchar *local_keyboard_path; keyboard_list = kmfl_get_keyboard_list("/usr/share/kmfl"); + engines = ibus_kmfl_add_engines(engines, keyboard_list); + g_list_free(keyboard_list); + keyboard_list = kmfl_get_keyboard_list("/usr/share/keyman"); engines = ibus_kmfl_add_engines(engines, keyboard_list); + g_list_free(keyboard_list); + keyboard_list = kmfl_get_keyboard_list("/usr/local/share/keyman"); + engines = ibus_kmfl_add_engines(engines, keyboard_list); g_list_free(keyboard_list); local_keyboard_path= g_strdup_printf("%s/.kmfl", getenv("HOME")); - keyboard_list = kmfl_get_keyboard_list(local_keyboard_path); - engines = ibus_kmfl_add_engines(engines, keyboard_list); - g_free(local_keyboard_path); + g_list_free(keyboard_list); + local_keyboard_path= g_strdup_printf("%s/.local/share/keyman", getenv("HOME")); + keyboard_list = kmfl_get_keyboard_list(local_keyboard_path); + engines = ibus_kmfl_add_engines(engines, keyboard_list); + g_free(local_keyboard_path); g_list_free(keyboard_list); - + return engines; } @@ -280,6 +381,94 @@ void kinput_close_im(KInputMethod * im) g_free(im); } +void output_string(void *contrack, char *ptr) { + KInputContext * ic = (KInputContext *)contrack; + g_debug("DAR: output_string - ic->cmds=%p", ic->cmds); + if (ptr) { + Cmd * cmd = g_new(Cmd, 1); + cmd->opcode=OUTPUT_STRING; + cmd->cmdarg=g_strdup(ptr); + ic->cmds = g_list_append(ic->cmds, cmd); + } +} + +void erase_char(void *contrack) { + KInputContext * ic = (KInputContext *)contrack; + g_debug("DAR: erase_char - ic->cmds=%p", ic->cmds); + Cmd * cmd = g_new(Cmd, 1); + cmd->opcode = ERASE_CHAR; + cmd->cmdarg=NULL; + ic->cmds = g_list_append(ic->cmds, cmd); +} + +void output_char(void *contrack, unsigned char byte) { + if (byte == 8) { + erase_char(contrack); + } else { + char s[2]; + s[0] = byte; + s[1] = '\0'; + output_string(contrack, s); + } +} + +void forward_keyevent(void *contrack, unsigned int key, unsigned int state) +{ + +} + +void output_beep(void *contrack) { + KInputContext * ic = (KInputContext *)contrack; + Cmd * cmd = g_new(Cmd, 1); + cmd->opcode = OUTPUT_BEEP; + cmd->cmdarg=NULL; + ic->cmds = g_list_append(ic->cmds, cmd); +} + + +/* + * Create an input context + */ +KInputContext * +kmfl_create_ic(KInputMethod *im) +{ + KInputContext * ic; + g_debug("DAR: kmfl_create_ic"); + ic = g_new(KInputContext, 1); + ic->cmds = NULL; + ic->p_kmsi=kmfl_make_keyboard_instance(ic); + kmfl_attach_keyboard(ic->p_kmsi, im->keyboard_number); + + return ic; +} + + +/* + * Destroy an input context + */ +void +kmfl_destroy_ic(KInputContext *ic) +{ + GList * p; + g_debug("DAR: kmfl_destroy_ic"); + kmfl_detach_keyboard(ic->p_kmsi); + kmfl_delete_keyboard_instance(ic->p_kmsi); + + if (ic->cmds) { + for (p=ic->cmds; p != NULL; p = p->next) { + Cmd * cmd = (Cmd *)p->data; + if (cmd) { + if (cmd->cmdarg) + g_free(cmd->cmdarg); + g_free(cmd); + } + } + g_list_free(ic->cmds); + ic->cmds=NULL; + } + +} + #ifdef DEBUG #include <locale.h> diff --git a/src/kmflutil.h b/src/kmflutil.h index 3da445a..1358d48 100644 --- a/src/kmflutil.h +++ b/src/kmflutil.h @@ -3,14 +3,42 @@ /* * KMFL Input Method for IBUS (The Input Bus) * - * Copyright (C) 2009 SIL International + * Copyright (C) 2009-2018 SIL International * - * This library is free software; you can redistribute it and/or + * kmflutil is dual licensed under the MIT or GPL licenses as described below. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * MIT license + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * OR + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * 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 library is distributed in the hope that it will be useful, + * 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. @@ -47,6 +75,7 @@ typedef struct int keyboard_number; gchar * keyboard_filename; gchar * keyboard_icon_filename; + gchar * keyboard_id; gchar * keyboard_name; gchar * keyboard_language; gchar * keyboard_author; @@ -54,6 +83,9 @@ typedef struct gchar * keyboard_description; gchar * keyboard_layout; gchar * keyboard_license; + gchar * keyboard_visualkeyboard; + gchar * keyboard_keyboardversion; + gchar * keyboard_ldmlfile; } KInputMethod; @@ -61,6 +93,8 @@ void ibus_kmfl_init (void); GList *ibus_kmfl_list_engines (void); IBusComponent *ibus_kmfl_get_component (void); KInputMethod *kinput_open_im (const gchar * keyboard_filename); +KInputContext *kmfl_create_ic (KInputMethod *im); +void kmfl_destroy_ic (KInputContext *ic); void kinput_close_im (KInputMethod * im); void kmfl_get_keyboard_info (KInputMethod * im); #endif @@ -27,6 +27,7 @@ #include <stdio.h> #include "kmflutil.h" #include "engine.h" +#include "keyman-service.h" static IBusBus *bus = NULL; static IBusFactory *factory = NULL; @@ -50,6 +51,9 @@ ibus_disconnected_cb (IBusBus *bus, gpointer user_data) { g_debug ("bus disconnected"); + KeymanService *service = km_service_get_default(); + g_clear_object(&service); + ibus_quit (); } @@ -88,6 +92,7 @@ start_component (void) } g_object_unref (component); + km_service_get_default(); // initialise dbus service ibus_main (); } |