diff options
author | glasseyes <dglassey@gmail.com> | 2019-01-04 23:58:46 +0700 |
---|---|---|
committer | glasseyes <dglassey@gmail.com> | 2019-01-04 23:58:46 +0700 |
commit | 0bb2eda66dff5dcbe9d3f53e2612e63c0e3d73fa (patch) | |
tree | 74d36ed666ec7c80bdcf2d96d1bd6807eaea8943 /src |
New upstream version 11.0.103
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 112 | ||||
-rw-r--r-- | src/Makefile.in | 1306 | ||||
-rw-r--r-- | src/engine.c | 978 | ||||
-rw-r--r-- | src/engine.h | 34 | ||||
-rw-r--r-- | src/keyman-service.c | 379 | ||||
-rw-r--r-- | src/keyman-service.h | 69 | ||||
-rw-r--r-- | src/keyman.xml.in | 18 | ||||
-rw-r--r-- | src/keyman.xml.in.in | 18 | ||||
-rw-r--r-- | src/keymanutil.c | 328 | ||||
-rw-r--r-- | src/keymanutil.h | 61 | ||||
-rw-r--r-- | src/kmpdetails.c | 476 | ||||
-rw-r--r-- | src/kmpdetails.h | 78 | ||||
-rw-r--r-- | src/main.c | 143 | ||||
-rw-r--r-- | src/print_kmp.c | 240 | ||||
-rw-r--r-- | src/print_kmpdetails.c | 41 | ||||
-rwxr-xr-x | src/test/print_kmp.test | 2 | ||||
-rwxr-xr-x | src/test/print_kmpdetails.test | 2 |
17 files changed, 4285 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..4db99bd --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,112 @@ +# vim:set noet ts=4: +# +# ibus-keyman - The Keyman engine for IBus +# +# Copyright (c) 2018 SIL International +# +# 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, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +AM_CFLAGS = \ + @IBUS_CFLAGS@ \ + @GTK_CFLAGS@ \ + @JSON_GLIB_CFLAGS@ \ + @KEYMAN_PROC_CFLAGS@ \ + -DPKGDATADIR=\"$(pkgdatadir)\" \ + $(NULL) + +AM_LDFLAGS = \ + @IBUS_LIBS@ \ + @GTK_LIBS@ \ + @JSON_GLIB_LIBS@ \ + @KEYMAN_PROC_LIBS@ \ + $(NULL) + +check_PROGRAMS = \ + print_kmpdetails \ + print_kmp \ + $(NULL) + +TESTS = \ + test/print_kmpdetails.test \ + test/print_kmp.test \ + $(NULL) + +print_kmp_SOURCES = \ + print_kmp.c + +print_kmpdetails_SOURCES = \ + kmpdetails.c \ + print_kmpdetails.c \ + $(NULL) +print_kmpdetails_CFLAGS = \ + $(AM_CFLAGS) \ + @JSON_GLIB_CFLAGS@ \ + -DDEBUG \ + $(NULL) + +libexec_PROGRAMS = ibus-engine-keyman + +ibus_engine_keyman_SOURCES = \ + keymanutil.c \ + keymanutil.h \ + kmpdetails.c \ + kmpdetails.h \ + main.c \ + engine.c \ + engine.h \ + keyman-service.c \ + keyman-service.h \ + $(NULL) + +ibus_engine_keyman_CFLAGS = \ + @IBUS_CFLAGS@ \ + @GTK_CFLAGS@ \ + @JSON_GLIB_CFLAGS@ \ + @KEYMAN_PROC_CFLAGS@ \ + -DPKGDATADIR=\"$(pkgdatadir)\" \ + $(NULL) + +ibus_engine_keyman_LDFLAGS = \ + @GTK_LIBS@ \ + @IBUS_LIBS@ \ + @JSON_GLIB_LIBS@ \ + @KEYMAN_PROC_LIBS@ \ + $(NULL) + +component_DATA = \ + keyman.xml \ + $(NULL) +componentdir = @datadir@/ibus/component + +EXTRA_DIST = \ + keyman.xml.in \ + test/print_kmpdetails.test \ + test/print_kmp.test \ + $(NULL) + +CLEANFILES = \ + keyman.xml \ + $(NULL) + +keyman.xml: keyman.xml.in + ( \ + libexecdir=${libexecdir}; \ + pkgdatadir=${pkgdatadir}; \ + s=`cat $<`; \ + eval "echo \"$${s}\""; \ + ) > $@ + +test: ibus-engine-keyman + $(builddir)/ibus-engine-keyman diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..42823c6 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,1306 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# vim:set noet ts=4: +# +# ibus-keyman - The Keyman engine for IBus +# +# Copyright (c) 2018 SIL International +# +# 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, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +VPATH = @srcdir@ +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 \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +check_PROGRAMS = print_kmpdetails$(EXEEXT) print_kmp$(EXEEXT) +TESTS = test/print_kmpdetails.test test/print_kmp.test +libexec_PROGRAMS = ibus-engine-keyman$(EXEEXT) +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.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 = keyman.xml.in +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" \ + "$(DESTDIR)$(componentdir)" +PROGRAMS = $(libexec_PROGRAMS) +am_ibus_engine_keyman_OBJECTS = \ + ibus_engine_keyman-keymanutil.$(OBJEXT) \ + ibus_engine_keyman-kmpdetails.$(OBJEXT) \ + ibus_engine_keyman-main.$(OBJEXT) \ + ibus_engine_keyman-engine.$(OBJEXT) \ + ibus_engine_keyman-keyman-service.$(OBJEXT) +ibus_engine_keyman_OBJECTS = $(am_ibus_engine_keyman_OBJECTS) +ibus_engine_keyman_LDADD = $(LDADD) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ibus_engine_keyman_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(ibus_engine_keyman_CFLAGS) $(CFLAGS) \ + $(ibus_engine_keyman_LDFLAGS) $(LDFLAGS) -o $@ +am_print_kmp_OBJECTS = print_kmp.$(OBJEXT) +print_kmp_OBJECTS = $(am_print_kmp_OBJECTS) +print_kmp_LDADD = $(LDADD) +am_print_kmpdetails_OBJECTS = print_kmpdetails-kmpdetails.$(OBJEXT) \ + print_kmpdetails-print_kmpdetails.$(OBJEXT) +print_kmpdetails_OBJECTS = $(am_print_kmpdetails_OBJECTS) +print_kmpdetails_LDADD = $(LDADD) +print_kmpdetails_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(print_kmpdetails_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(ibus_engine_keyman_SOURCES) $(print_kmp_SOURCES) \ + $(print_kmpdetails_SOURCES) +DIST_SOURCES = $(ibus_engine_keyman_SOURCES) $(print_kmp_SOURCES) \ + $(print_kmpdetails_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +DATA = $(component_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +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__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/keyman.xml.in.in \ + $(top_srcdir)/depcomp $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENV = @ENV@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +IBUS_CFLAGS = @IBUS_CFLAGS@ +IBUS_LIBS = @IBUS_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@ +JSON_GLIB_LIBS = @JSON_GLIB_LIBS@ +KEYMAN_PROC_CFLAGS = @KEYMAN_PROC_CFLAGS@ +KEYMAN_PROC_LIBS = @KEYMAN_PROC_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +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@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = \ + @IBUS_CFLAGS@ \ + @GTK_CFLAGS@ \ + @JSON_GLIB_CFLAGS@ \ + @KEYMAN_PROC_CFLAGS@ \ + -DPKGDATADIR=\"$(pkgdatadir)\" \ + $(NULL) + +AM_LDFLAGS = \ + @IBUS_LIBS@ \ + @GTK_LIBS@ \ + @JSON_GLIB_LIBS@ \ + @KEYMAN_PROC_LIBS@ \ + $(NULL) + +print_kmp_SOURCES = \ + print_kmp.c + +print_kmpdetails_SOURCES = \ + kmpdetails.c \ + print_kmpdetails.c \ + $(NULL) + +print_kmpdetails_CFLAGS = \ + $(AM_CFLAGS) \ + @JSON_GLIB_CFLAGS@ \ + -DDEBUG \ + $(NULL) + +ibus_engine_keyman_SOURCES = \ + keymanutil.c \ + keymanutil.h \ + kmpdetails.c \ + kmpdetails.h \ + main.c \ + engine.c \ + engine.h \ + keyman-service.c \ + keyman-service.h \ + $(NULL) + +ibus_engine_keyman_CFLAGS = \ + @IBUS_CFLAGS@ \ + @GTK_CFLAGS@ \ + @JSON_GLIB_CFLAGS@ \ + @KEYMAN_PROC_CFLAGS@ \ + -DPKGDATADIR=\"$(pkgdatadir)\" \ + $(NULL) + +ibus_engine_keyman_LDFLAGS = \ + @GTK_LIBS@ \ + @IBUS_LIBS@ \ + @JSON_GLIB_LIBS@ \ + @KEYMAN_PROC_LIBS@ \ + $(NULL) + +component_DATA = \ + keyman.xml \ + $(NULL) + +componentdir = @datadir@/ibus/component +EXTRA_DIST = \ + keyman.xml.in \ + test/print_kmpdetails.test \ + test/print_kmp.test \ + $(NULL) + +CLEANFILES = \ + keyman.xml \ + $(NULL) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +keyman.xml.in: $(top_builddir)/config.status $(srcdir)/keyman.xml.in.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +ibus-engine-keyman$(EXEEXT): $(ibus_engine_keyman_OBJECTS) $(ibus_engine_keyman_DEPENDENCIES) $(EXTRA_ibus_engine_keyman_DEPENDENCIES) + @rm -f ibus-engine-keyman$(EXEEXT) + $(AM_V_CCLD)$(ibus_engine_keyman_LINK) $(ibus_engine_keyman_OBJECTS) $(ibus_engine_keyman_LDADD) $(LIBS) + +print_kmp$(EXEEXT): $(print_kmp_OBJECTS) $(print_kmp_DEPENDENCIES) $(EXTRA_print_kmp_DEPENDENCIES) + @rm -f print_kmp$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(print_kmp_OBJECTS) $(print_kmp_LDADD) $(LIBS) + +print_kmpdetails$(EXEEXT): $(print_kmpdetails_OBJECTS) $(print_kmpdetails_DEPENDENCIES) $(EXTRA_print_kmpdetails_DEPENDENCIES) + @rm -f print_kmpdetails$(EXEEXT) + $(AM_V_CCLD)$(print_kmpdetails_LINK) $(print_kmpdetails_OBJECTS) $(print_kmpdetails_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_keyman-engine.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_keyman-keyman-service.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_keyman-keymanutil.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_keyman-kmpdetails.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibus_engine_keyman-main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_kmp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_kmpdetails-kmpdetails.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_kmpdetails-print_kmpdetails.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +ibus_engine_keyman-keymanutil.o: keymanutil.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-keymanutil.o -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-keymanutil.Tpo -c -o ibus_engine_keyman-keymanutil.o `test -f 'keymanutil.c' || echo '$(srcdir)/'`keymanutil.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-keymanutil.Tpo $(DEPDIR)/ibus_engine_keyman-keymanutil.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keymanutil.c' object='ibus_engine_keyman-keymanutil.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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-keymanutil.o `test -f 'keymanutil.c' || echo '$(srcdir)/'`keymanutil.c + +ibus_engine_keyman-keymanutil.obj: keymanutil.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-keymanutil.obj -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-keymanutil.Tpo -c -o ibus_engine_keyman-keymanutil.obj `if test -f 'keymanutil.c'; then $(CYGPATH_W) 'keymanutil.c'; else $(CYGPATH_W) '$(srcdir)/keymanutil.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-keymanutil.Tpo $(DEPDIR)/ibus_engine_keyman-keymanutil.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keymanutil.c' object='ibus_engine_keyman-keymanutil.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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-keymanutil.obj `if test -f 'keymanutil.c'; then $(CYGPATH_W) 'keymanutil.c'; else $(CYGPATH_W) '$(srcdir)/keymanutil.c'; fi` + +ibus_engine_keyman-kmpdetails.o: kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-kmpdetails.o -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-kmpdetails.Tpo -c -o ibus_engine_keyman-kmpdetails.o `test -f 'kmpdetails.c' || echo '$(srcdir)/'`kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-kmpdetails.Tpo $(DEPDIR)/ibus_engine_keyman-kmpdetails.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kmpdetails.c' object='ibus_engine_keyman-kmpdetails.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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-kmpdetails.o `test -f 'kmpdetails.c' || echo '$(srcdir)/'`kmpdetails.c + +ibus_engine_keyman-kmpdetails.obj: kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-kmpdetails.obj -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-kmpdetails.Tpo -c -o ibus_engine_keyman-kmpdetails.obj `if test -f 'kmpdetails.c'; then $(CYGPATH_W) 'kmpdetails.c'; else $(CYGPATH_W) '$(srcdir)/kmpdetails.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-kmpdetails.Tpo $(DEPDIR)/ibus_engine_keyman-kmpdetails.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kmpdetails.c' object='ibus_engine_keyman-kmpdetails.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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-kmpdetails.obj `if test -f 'kmpdetails.c'; then $(CYGPATH_W) 'kmpdetails.c'; else $(CYGPATH_W) '$(srcdir)/kmpdetails.c'; fi` + +ibus_engine_keyman-main.o: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-main.o -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-main.Tpo -c -o ibus_engine_keyman-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-main.Tpo $(DEPDIR)/ibus_engine_keyman-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='ibus_engine_keyman-main.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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c + +ibus_engine_keyman-main.obj: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-main.obj -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-main.Tpo -c -o ibus_engine_keyman-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-main.Tpo $(DEPDIR)/ibus_engine_keyman-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='ibus_engine_keyman-main.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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` + +ibus_engine_keyman-engine.o: engine.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-engine.o -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-engine.Tpo -c -o ibus_engine_keyman-engine.o `test -f 'engine.c' || echo '$(srcdir)/'`engine.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-engine.Tpo $(DEPDIR)/ibus_engine_keyman-engine.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='engine.c' object='ibus_engine_keyman-engine.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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-engine.o `test -f 'engine.c' || echo '$(srcdir)/'`engine.c + +ibus_engine_keyman-engine.obj: engine.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-engine.obj -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-engine.Tpo -c -o ibus_engine_keyman-engine.obj `if test -f 'engine.c'; then $(CYGPATH_W) 'engine.c'; else $(CYGPATH_W) '$(srcdir)/engine.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-engine.Tpo $(DEPDIR)/ibus_engine_keyman-engine.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='engine.c' object='ibus_engine_keyman-engine.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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-engine.obj `if test -f 'engine.c'; then $(CYGPATH_W) 'engine.c'; else $(CYGPATH_W) '$(srcdir)/engine.c'; fi` + +ibus_engine_keyman-keyman-service.o: keyman-service.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-keyman-service.o -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-keyman-service.Tpo -c -o ibus_engine_keyman-keyman-service.o `test -f 'keyman-service.c' || echo '$(srcdir)/'`keyman-service.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ibus_engine_keyman-keyman-service.Tpo $(DEPDIR)/ibus_engine_keyman-keyman-service.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keyman-service.c' object='ibus_engine_keyman-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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-keyman-service.o `test -f 'keyman-service.c' || echo '$(srcdir)/'`keyman-service.c + +ibus_engine_keyman-keyman-service.obj: keyman-service.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ibus_engine_keyman_CFLAGS) $(CFLAGS) -MT ibus_engine_keyman-keyman-service.obj -MD -MP -MF $(DEPDIR)/ibus_engine_keyman-keyman-service.Tpo -c -o ibus_engine_keyman-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_keyman-keyman-service.Tpo $(DEPDIR)/ibus_engine_keyman-keyman-service.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='keyman-service.c' object='ibus_engine_keyman-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_keyman_CFLAGS) $(CFLAGS) -c -o ibus_engine_keyman-keyman-service.obj `if test -f 'keyman-service.c'; then $(CYGPATH_W) 'keyman-service.c'; else $(CYGPATH_W) '$(srcdir)/keyman-service.c'; fi` + +print_kmpdetails-kmpdetails.o: kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(print_kmpdetails_CFLAGS) $(CFLAGS) -MT print_kmpdetails-kmpdetails.o -MD -MP -MF $(DEPDIR)/print_kmpdetails-kmpdetails.Tpo -c -o print_kmpdetails-kmpdetails.o `test -f 'kmpdetails.c' || echo '$(srcdir)/'`kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/print_kmpdetails-kmpdetails.Tpo $(DEPDIR)/print_kmpdetails-kmpdetails.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kmpdetails.c' object='print_kmpdetails-kmpdetails.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) $(print_kmpdetails_CFLAGS) $(CFLAGS) -c -o print_kmpdetails-kmpdetails.o `test -f 'kmpdetails.c' || echo '$(srcdir)/'`kmpdetails.c + +print_kmpdetails-kmpdetails.obj: kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(print_kmpdetails_CFLAGS) $(CFLAGS) -MT print_kmpdetails-kmpdetails.obj -MD -MP -MF $(DEPDIR)/print_kmpdetails-kmpdetails.Tpo -c -o print_kmpdetails-kmpdetails.obj `if test -f 'kmpdetails.c'; then $(CYGPATH_W) 'kmpdetails.c'; else $(CYGPATH_W) '$(srcdir)/kmpdetails.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/print_kmpdetails-kmpdetails.Tpo $(DEPDIR)/print_kmpdetails-kmpdetails.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kmpdetails.c' object='print_kmpdetails-kmpdetails.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) $(print_kmpdetails_CFLAGS) $(CFLAGS) -c -o print_kmpdetails-kmpdetails.obj `if test -f 'kmpdetails.c'; then $(CYGPATH_W) 'kmpdetails.c'; else $(CYGPATH_W) '$(srcdir)/kmpdetails.c'; fi` + +print_kmpdetails-print_kmpdetails.o: print_kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(print_kmpdetails_CFLAGS) $(CFLAGS) -MT print_kmpdetails-print_kmpdetails.o -MD -MP -MF $(DEPDIR)/print_kmpdetails-print_kmpdetails.Tpo -c -o print_kmpdetails-print_kmpdetails.o `test -f 'print_kmpdetails.c' || echo '$(srcdir)/'`print_kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/print_kmpdetails-print_kmpdetails.Tpo $(DEPDIR)/print_kmpdetails-print_kmpdetails.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='print_kmpdetails.c' object='print_kmpdetails-print_kmpdetails.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) $(print_kmpdetails_CFLAGS) $(CFLAGS) -c -o print_kmpdetails-print_kmpdetails.o `test -f 'print_kmpdetails.c' || echo '$(srcdir)/'`print_kmpdetails.c + +print_kmpdetails-print_kmpdetails.obj: print_kmpdetails.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(print_kmpdetails_CFLAGS) $(CFLAGS) -MT print_kmpdetails-print_kmpdetails.obj -MD -MP -MF $(DEPDIR)/print_kmpdetails-print_kmpdetails.Tpo -c -o print_kmpdetails-print_kmpdetails.obj `if test -f 'print_kmpdetails.c'; then $(CYGPATH_W) 'print_kmpdetails.c'; else $(CYGPATH_W) '$(srcdir)/print_kmpdetails.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/print_kmpdetails-print_kmpdetails.Tpo $(DEPDIR)/print_kmpdetails-print_kmpdetails.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='print_kmpdetails.c' object='print_kmpdetails-print_kmpdetails.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) $(print_kmpdetails_CFLAGS) $(CFLAGS) -c -o print_kmpdetails-print_kmpdetails.obj `if test -f 'print_kmpdetails.c'; then $(CYGPATH_W) 'print_kmpdetails.c'; else $(CYGPATH_W) '$(srcdir)/print_kmpdetails.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-componentDATA: $(component_DATA) + @$(NORMAL_INSTALL) + @list='$(component_DATA)'; test -n "$(componentdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(componentdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(componentdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(componentdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(componentdir)" || exit $$?; \ + done + +uninstall-componentDATA: + @$(NORMAL_UNINSTALL) + @list='$(component_DATA)'; test -n "$(componentdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(componentdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(componentdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-componentDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-componentDATA uninstall-libexecPROGRAMS + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ + clean-libtool cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-componentDATA install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libexecPROGRAMS install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am uninstall \ + uninstall-am uninstall-componentDATA uninstall-libexecPROGRAMS + +.PRECIOUS: Makefile + + +keyman.xml: keyman.xml.in + ( \ + libexecdir=${libexecdir}; \ + pkgdatadir=${pkgdatadir}; \ + s=`cat $<`; \ + eval "echo \"$${s}\""; \ + ) > $@ + +test: ibus-engine-keyman + $(builddir)/ibus-engine-keyman + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/engine.c b/src/engine.c new file mode 100644 index 0000000..586a85a --- /dev/null +++ b/src/engine.c @@ -0,0 +1,978 @@ +/* vim:set et sts=4: */ + +/* + * Keyman Input Method for IBUS (The Input Bus) + * + * Copyright (C) 2009-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 + * + */ + +#include <ibus.h> +#include <string.h> +#include <stdio.h> + +#include <gdk/gdk.h> +#include <keyman/keyboardprocessor.h> + +#include "keymanutil.h" +#include "keyman-service.h" +#include "engine.h" + +#define MAXCONTEXT_ITEMS 128 +#define KEYMAN_BACKSPACE 14 +#define KEYMAN_BACKSPACE_KEYSYM 0xff08 +#define KEYMAN_LCTRL 29 +#define KEYMAN_LALT 56 +#define KEYMAN_RCTRL 97 +#define KEYMAN_RALT 100 + +typedef struct _IBusKeymanEngine IBusKeymanEngine; +typedef struct _IBusKeymanEngineClass IBusKeymanEngineClass; + +struct _IBusKeymanEngine { + IBusEngine parent; + + /* members */ + km_kbp_keyboard *keyboard; + km_kbp_state *state; + gchar *ldmlfile; + gchar *kb_name; + gchar *char_buffer; + gunichar firstsurrogate; + gboolean lctrl_pressed; + gboolean rctrl_pressed; + gboolean lalt_pressed; + gboolean ralt_pressed; + gboolean emitting_keystroke; + IBusLookupTable *table; + IBusProperty *status_prop; + IBusPropList *prop_list; +}; + +struct _IBusKeymanEngineClass { + IBusEngineClass parent; +}; + +/* functions prototype */ +static void ibus_keyman_engine_class_init (IBusKeymanEngineClass *klass); +static void ibus_keyman_engine_init (IBusKeymanEngine *kmfl); +static GObject* + ibus_keyman_engine_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params); +static void ibus_keyman_engine_destroy (IBusKeymanEngine *kmfl); +static gboolean + ibus_keyman_engine_process_key_event + (IBusEngine *engine, + guint keyval, + guint keycode, + guint state); +static void ibus_keyman_engine_focus_in (IBusEngine *engine); +static void ibus_keyman_engine_focus_out (IBusEngine *engine); +static void ibus_keyman_engine_reset (IBusEngine *engine); +static void ibus_keyman_engine_enable (IBusEngine *engine); +static void ibus_keyman_engine_disable (IBusEngine *engine); +static void ibus_keyman_engine_set_surrounding_text( + IBusEngine *engine, + IBusText *text, + guint cursor_pos, + guint anchor_pos); +// static void ibus_keyman_engine_set_cursor_location (IBusEngine *engine, +// gint x, +// gint y, +// gint w, +// gint h); +static void ibus_keyman_engine_set_capabilities( + IBusEngine *engine, + guint caps); +// static void ibus_keyman_engine_page_up (IBusEngine *engine); +// static void ibus_keyman_engine_page_down (IBusEngine *engine); +// static void ibus_keyman_engine_cursor_up (IBusEngine *engine); +// static void ibus_keyman_engine_cursor_down (IBusEngine *engine); +static void ibus_keyman_engine_property_activate + (IBusEngine *engine, + const gchar *prop_name, + guint prop_state); +static void ibus_keyman_engine_property_show + (IBusEngine *engine, + const gchar *prop_name); +static void ibus_keyman_engine_property_hide + (IBusEngine *engine, + const gchar *prop_name); + +static void ibus_keyman_engine_commit_string + (IBusKeymanEngine *kmfl, + const gchar *string); + +static IBusEngineClass *parent_class = NULL; + +GType +ibus_keyman_engine_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusKeymanEngineClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_keyman_engine_class_init, + NULL, + NULL, + sizeof (IBusKeymanEngine), + 0, + (GInstanceInitFunc) ibus_keyman_engine_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_ENGINE, + "IBusKeymanEngine", + &type_info, + (GTypeFlags) 0); + } + + return type; +} + +static void +ibus_keyman_engine_class_init (IBusKeymanEngineClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass); + + parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass); + + object_class->constructor = ibus_keyman_engine_constructor; + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_keyman_engine_destroy; + + engine_class->process_key_event = ibus_keyman_engine_process_key_event; + + engine_class->reset = ibus_keyman_engine_reset; + engine_class->enable = ibus_keyman_engine_enable; + engine_class->disable = ibus_keyman_engine_disable; + + engine_class->set_surrounding_text = ibus_keyman_engine_set_surrounding_text; + // engine_class->set_cursor_location = ibus_keyman_engine_set_cursor_location; + + + engine_class->focus_in = ibus_keyman_engine_focus_in; + engine_class->focus_out = ibus_keyman_engine_focus_out; + + // engine_class->page_up = ibus_keyman_engine_page_up; + // engine_class->page_down = ibus_keyman_engine_page_down; + + // engine_class->cursor_up = ibus_keyman_engine_cursor_up; + // engine_class->cursor_down = ibus_keyman_engine_cursor_down; + + engine_class->property_activate = ibus_keyman_engine_property_activate; +} + +static gchar *get_current_context_text(km_kbp_context *context) +{ + size_t buf_size = 512; + km_kbp_context_item *context_items; + gchar *current_context_utf8 = g_new0(gchar, buf_size); + if (km_kbp_context_get(context, &context_items) == KM_KBP_STATUS_OK) { + km_kbp_context_items_to_utf8(context_items, + current_context_utf8, + &buf_size); + } + km_kbp_context_items_dispose(context_items); + g_message("current context is:%lu:%lu:%s:", km_kbp_context_length(context), buf_size, current_context_utf8); + return current_context_utf8; +} + +static void reset_context(IBusEngine *engine) +{ + IBusKeymanEngine *keyman = (IBusKeymanEngine *) engine; + IBusText *text; + gchar *surrounding_text, *current_context_utf8; + guint cursor_pos, anchor_pos, context_start, context_pos; + km_kbp_context_item *context_items; + km_kbp_context *context; + + g_message("reset_context"); + keyman->firstsurrogate = 0; + context = km_kbp_state_context(keyman->state); + if ((engine->client_capabilities & IBUS_CAP_SURROUNDING_TEXT) != 0) + { + current_context_utf8 = get_current_context_text(context); + + ibus_engine_get_surrounding_text(engine, &text, &cursor_pos, &anchor_pos); + context_pos = anchor_pos < cursor_pos ? anchor_pos : cursor_pos; + context_start = context_pos > MAXCONTEXT_ITEMS ? context_pos - MAXCONTEXT_ITEMS : 0; + surrounding_text = g_utf8_substring(ibus_text_get_text(text), context_start, context_pos); + g_message("new context is:%u:%s: cursor:%d anchor:%d", context_pos - context_start, surrounding_text, cursor_pos, anchor_pos); + + g_message(":%s:%s:", surrounding_text, current_context_utf8); + if (g_strcmp0(surrounding_text, current_context_utf8) != 0) + { + g_message("setting context because it has changed from expected"); + if (km_kbp_context_items_from_utf8(surrounding_text, &context_items) == KM_KBP_STATUS_OK) { + km_kbp_context_set(context, context_items); + } + km_kbp_context_items_dispose(context_items); + } + g_free(surrounding_text); + g_free(current_context_utf8); + } + else { + km_kbp_context_clear(context); + } +} + +static void +ibus_keyman_engine_init (IBusKeymanEngine *kmfl) +{ + kmfl->status_prop = ibus_property_new ("status", + PROP_TYPE_NORMAL, + NULL, + NULL, + NULL, + TRUE, + FALSE, + 0, + NULL); + g_object_ref_sink(kmfl->status_prop); + kmfl->prop_list = ibus_prop_list_new (); + g_object_ref_sink(kmfl->prop_list); + ibus_prop_list_append (kmfl->prop_list, kmfl->status_prop); + + kmfl->table = ibus_lookup_table_new (9, 0, TRUE, TRUE); + g_object_ref_sink(kmfl->table); + kmfl->state = NULL; +} + +static GObject* +ibus_keyman_engine_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + IBusKeymanEngine *keyman; + IBusEngine *engine; + IBusText *text; + const gchar *engine_name; + gchar *surrounding_text, *p, *abs_kmx_path; + guint cursor_pos, anchor_pos; + km_kbp_context_item *context_items; + + g_debug("DAR: ibus_keyman_engine_constructor"); + + keyman = (IBusKeymanEngine *) G_OBJECT_CLASS (parent_class)->constructor (type, + n_construct_params, + construct_params); + + engine = (IBusEngine *) keyman; + engine_name = ibus_engine_get_name (engine); + g_assert (engine_name); + g_message("DAR: ibus_keyman_engine_constructor %s", engine_name); + + keyman->kb_name = NULL; + keyman->ldmlfile = NULL; + keyman->firstsurrogate = 0; + keyman->lalt_pressed = FALSE; + keyman->lctrl_pressed = FALSE; + keyman->ralt_pressed = FALSE; + keyman->rctrl_pressed = FALSE; + keyman->emitting_keystroke = FALSE; + gchar **split_name = g_strsplit(engine_name, ":", 2); + if (split_name[0] == NULL) + { + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)keyman); + return NULL; + } + else if (split_name[1] == NULL) + { + abs_kmx_path = g_strdup(split_name[0]); + } + else + { + abs_kmx_path = g_strdup(split_name[1]); + } + + g_strfreev(split_name); + + gchar *kmx_file = g_path_get_basename(abs_kmx_path); + p = rindex(kmx_file, '.'); // get id to use as dbus service name + if (p) { + keyman->kb_name = g_strndup(kmx_file, p-kmx_file); + p = rindex(abs_kmx_path, '.'); + if (p) + { + gchar *dir = g_path_get_dirname(abs_kmx_path); + gchar *ldmlfile = g_strdup_printf("%s/%s.ldml", dir, keyman->kb_name); + if (g_file_test(ldmlfile, G_FILE_TEST_EXISTS)) + { + keyman->ldmlfile = g_strdup(ldmlfile); + } + g_free(dir); + g_free(ldmlfile); + } + } + g_free(kmx_file); + + km_kbp_option_item *keyboard_opts = g_new0(km_kbp_option_item, 4); + + keyboard_opts[0].scope = KM_KBP_OPT_ENVIRONMENT; + km_kbp_cp *cp = g_utf8_to_utf16 ("platform", -1, NULL, NULL, NULL); + keyboard_opts[0].key = cp; + cp = g_utf8_to_utf16 ("linux desktop hardware native", -1, NULL, NULL, NULL); + keyboard_opts[0].value = cp; + + keyboard_opts[1].scope = KM_KBP_OPT_ENVIRONMENT; + cp = g_utf8_to_utf16 ("baseLayout", -1, NULL, NULL, NULL); + keyboard_opts[1].key = cp; + cp = g_utf8_to_utf16 ("kbdus.dll", -1, NULL, NULL, NULL); + keyboard_opts[1].value = cp; + + keyboard_opts[2].scope = KM_KBP_OPT_ENVIRONMENT; + cp = g_utf8_to_utf16 ("baseLayoutAlt", -1, NULL, NULL, NULL); + keyboard_opts[2].key = cp; + #if 0 // in the future when mnemonic layouts are to be supported + const gchar *lang_env = g_getenv("LANG"); + gchar *lang; + if (lang_env != NULL) { + g_message("LANG=%s", lang_env); + gchar **splitlang = g_strsplit(lang_env, ".", 2); + g_message("before . is %s", splitlang[0]); + if (g_strrstr(splitlang[0], "_")) { + g_message("splitting %s", splitlang[0]); + gchar **taglang = g_strsplit(splitlang[0], "_", 2); + g_message("lang of tag is %s", taglang[0]); + g_message("country of tag is %s", taglang[1]); + lang = g_strjoin("-", taglang[0], taglang[1], NULL); + g_strfreev(taglang); + } + else { + lang = g_strdup(splitlang[0]); + } + g_strfreev(splitlang); + } + else { + lang = strdup("en-US"); + } + g_message("lang is %s", lang); + #endif + cp = g_utf8_to_utf16 ("en-US", -1, NULL, NULL, NULL); + // g_free(lang); + keyboard_opts[2].value = cp; + + // keyboard_opts[3] already initialised to {0, 0, 0} + + km_kbp_status status_keyboard = km_kbp_keyboard_load(abs_kmx_path, &(keyman->keyboard)); + g_free(abs_kmx_path); + + if (status_keyboard != KM_KBP_STATUS_OK) + { + g_warning("problem creating km_kbp_keyboard"); + } + + km_kbp_status status_state = km_kbp_state_create(keyman->keyboard, + keyboard_opts, + &(keyman->state)); + if (status_state != KM_KBP_STATUS_OK) + { + g_warning("problem creating km_kbp_state"); + } + for (int i =0; i < 3; i++) { + g_free((km_kbp_cp *)keyboard_opts[i].key); + g_free((km_kbp_cp *)keyboard_opts[i].value); + } + g_free(keyboard_opts); + + reset_context(engine); + + return (GObject *) keyman; +} + + +static void +ibus_keyman_engine_destroy (IBusKeymanEngine *keyman) +{ + const gchar *engine_name; + + g_debug("DAR: ibus_keyman_engine_destroy"); + engine_name = ibus_engine_get_name ((IBusEngine *) keyman); + g_assert (engine_name); + g_message("DAR: ibus_keyman_engine_destroy %s", engine_name); + + if (keyman->prop_list) { + g_debug("DAR: unref keyman->prop_list"); + g_object_unref (keyman->prop_list); + keyman->prop_list = NULL; + } + + if (keyman->status_prop) { + g_debug("DAR: unref keyman->status_prop"); + g_object_unref (keyman->status_prop); + keyman->status_prop = NULL; + } + + if (keyman->table) { + g_debug("DAR: unref keyman->table"); + g_object_unref (keyman->table); + keyman->table = NULL; + } + if (keyman->state) { + km_kbp_state_dispose(keyman->state); + keyman->state = NULL; + } + + if (keyman->keyboard) { + km_kbp_keyboard_dispose(keyman->keyboard); + keyman->keyboard = NULL; + } + + g_free(keyman->kb_name); + g_free(keyman->ldmlfile); + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)keyman); +} + +static void +ibus_keyman_engine_commit_string (IBusKeymanEngine *kmfl, + const gchar *string) +{ + IBusText *text; + g_message("DAR: ibus_keyman_engine_commit_string - %s", string); + text = ibus_text_new_from_static_string (string); + g_object_ref_sink(text); + ibus_engine_commit_text ((IBusEngine *)kmfl, text); + g_object_unref (text); +} + +static void forward_backspace(IBusKeymanEngine *engine, unsigned int state) +{ + g_message("DAR: forward_backspace %d no keysym state %d", KEYMAN_BACKSPACE, state); + ibus_engine_forward_key_event((IBusEngine *)engine, KEYMAN_BACKSPACE_KEYSYM, KEYMAN_BACKSPACE, state); +} + +// from android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMHardwareKeyboardInterpreter.java +// uses kernel keycodes which are X11 keycode - 8 +//private static final +// int scanCodeMap[] = { +static km_kbp_virtual_key const keycode_to_vk[256] = { + 0, // padding = 0x00; + KM_KBP_VKEY_ESC, // public static final int KEY_ESC = 0x01; + KM_KBP_VKEY_1, // public static final int KEY_1 = 0x02; + KM_KBP_VKEY_2, // public static final int KEY_2 = 0x03; + KM_KBP_VKEY_3, // public static final int KEY_3 = 0x04; + KM_KBP_VKEY_4, // public static final int KEY_4 = 0x05; + KM_KBP_VKEY_5, // public static final int KEY_5 = 0x06; + KM_KBP_VKEY_6, // public static final int KEY_6 = 0x07; + KM_KBP_VKEY_7, // public static final int KEY_7 = 0x08; + KM_KBP_VKEY_8, // public static final int KEY_8 = 0x09; + KM_KBP_VKEY_9, // public static final int KEY_9 = 0x0A; + KM_KBP_VKEY_0, // public static final int KEY_0 = 0x0B; + KM_KBP_VKEY_HYPHEN, // public static final int KEY_MINUS = 0x0C; + KM_KBP_VKEY_EQUAL, // public static final int KEY_EQUALS = 0x0D; + KM_KBP_VKEY_BKSP, // public static final int KEY_BACKSPACE = 0x0E; + KM_KBP_VKEY_TAB, // public static final int KEY_TAB = 0x0F; + KM_KBP_VKEY_Q, // public static final int KEY_Q = 0x10; + KM_KBP_VKEY_W, // public static final int KEY_W = 0x11; + KM_KBP_VKEY_E, // public static final int KEY_E = 0x12; + KM_KBP_VKEY_R, // public static final int KEY_R = 0x13; + KM_KBP_VKEY_T, // public static final int KEY_T = 0x14; + KM_KBP_VKEY_Y, // public static final int KEY_Y = 0x15; + KM_KBP_VKEY_U, // public static final int KEY_U = 0x16; + KM_KBP_VKEY_I, // public static final int KEY_I = 0x17; + KM_KBP_VKEY_O, // public static final int KEY_O = 0x18; + KM_KBP_VKEY_P, // public static final int KEY_P = 0x19; + KM_KBP_VKEY_LBRKT, // public static final int KEY_LEFTBRACE = 0x1A; + KM_KBP_VKEY_RBRKT, // public static final int KEY_RIGHTBRACE = 0x1B; + KM_KBP_VKEY_ENTER, // public static final int KEY_ENTER = 0x1C; + 0, // public static final int KEY_LEFTCTRL = 0x1D; + KM_KBP_VKEY_A, // public static final int KEY_A = 0x1E; + KM_KBP_VKEY_S, // public static final int KEY_S = 0x1F; + KM_KBP_VKEY_D, // public static final int KEY_D = 0x20; + KM_KBP_VKEY_F, // public static final int KEY_F = 0x21; + KM_KBP_VKEY_G, // public static final int KEY_G = 0x22; + KM_KBP_VKEY_H, // public static final int KEY_H = 0x23; + KM_KBP_VKEY_J, // public static final int KEY_J = 0x24; + KM_KBP_VKEY_K, // public static final int KEY_K = 0x25; + KM_KBP_VKEY_L, // public static final int KEY_L = 0x26; + KM_KBP_VKEY_COLON, // public static final int KEY_SEMICOLON = 0x27; + KM_KBP_VKEY_QUOTE, // public static final int KEY_APOSTROPHE = 0x28; + KM_KBP_VKEY_BKQUOTE, // public static final int KEY_GRAVE = 0x29; + 0, // public static final int KEY_LEFTSHIFT = 0x2A; + KM_KBP_VKEY_BKSLASH, // public static final int KEY_BACKSLASH = 0x2B; + KM_KBP_VKEY_Z, // public static final int KEY_Z = 0x2C; + KM_KBP_VKEY_X, // public static final int KEY_X = 0x2D; + KM_KBP_VKEY_C, // public static final int KEY_C = 0x2E; + KM_KBP_VKEY_V, // public static final int KEY_V = 0x2F; + KM_KBP_VKEY_B, // public static final int KEY_B = 0x30; + KM_KBP_VKEY_N, // public static final int KEY_N = 0x31; + KM_KBP_VKEY_M, // public static final int KEY_M = 0x32; + KM_KBP_VKEY_COMMA, // public static final int KEY_COMMA = 0x33; + KM_KBP_VKEY_PERIOD, // public static final int KEY_DOT = 0x34; + KM_KBP_VKEY_SLASH, // public static final int KEY_SLASH = 0x35; + 0, // public static final int KEY_RIGHTSHIFT = 0x36; + KM_KBP_VKEY_NPSTAR, // public static final int KEY_KPASTERISK = 0x37; + 0, // public static final int KEY_LEFTALT = 0x38; + KM_KBP_VKEY_SPACE, // public static final int KEY_SPACE = 0x39; + 0, // public static final int KEY_CAPSLOCK = 0x3A; + KM_KBP_VKEY_F1, // public static final int KEY_F1 = 0x3B; + KM_KBP_VKEY_F2, // public static final int KEY_F2 = 0x3C; + KM_KBP_VKEY_F3, // public static final int KEY_F3 = 0x3D; + KM_KBP_VKEY_F4, // public static final int KEY_F4 = 0x3E; + KM_KBP_VKEY_F5, // public static final int KEY_F5 = 0x3F; + KM_KBP_VKEY_F6, // public static final int KEY_F6 = 0x40; + KM_KBP_VKEY_F7, // public static final int KEY_F7 = 0x41; + KM_KBP_VKEY_F8, // public static final int KEY_F8 = 0x42; + KM_KBP_VKEY_F9, // public static final int KEY_F9 = 0x43; + KM_KBP_VKEY_F10, // public static final int KEY_F10 = 0x44; + 0, // public static final int KEY_NUMLOCK = 0x45; + 0, // public static final int KEY_SCROLLLOCK = 0x46; + KM_KBP_VKEY_NP7, // public static final int KEY_KP7 = 0x47; + KM_KBP_VKEY_NP8, // public static final int KEY_KP8 = 0x48; + KM_KBP_VKEY_NP9, // public static final int KEY_KP9 = 0x49; + KM_KBP_VKEY_NPMINUS, // public static final int KEY_KPMINUS = 0x4A; + KM_KBP_VKEY_NP4, // public static final int KEY_KP4 = 0x4B; + KM_KBP_VKEY_NP5, // public static final int KEY_KP5 = 0x4C; + KM_KBP_VKEY_NP6, // public static final int KEY_KP6 = 0x4D; + KM_KBP_VKEY_NPPLUS, // public static final int KEY_KPPLUS = 0x4E; + KM_KBP_VKEY_NP1, // public static final int KEY_KP1 = 0x4F; + KM_KBP_VKEY_NP2, // public static final int KEY_KP2 = 0x50; + KM_KBP_VKEY_NP3, // public static final int KEY_KP3 = 0x51; + KM_KBP_VKEY_NP0, // public static final int KEY_KP0 = 0x52; + KM_KBP_VKEY_NPDOT, // public static final int KEY_KPDOT = 0x53; + 0, // padding 0x54; + 0, // public static final int KEY_ZENKAKUHANKAKU = 0x55; + KM_KBP_VKEY_oE2, // public static final int KEY_102ND = 0x56; + // additional on linux + KM_KBP_VKEY_F11, // public static final int KEY_F11 = 0x57; + KM_KBP_VKEY_F12 // public static final int KEY_F12 = 0x58; + + // Many more KEYS currently not used by KMW... + }; + +static gboolean ok_for_single_backspace(const km_kbp_action_item *action_items, int i, size_t num_actions) +{ + for (int j=i+1; j < num_actions; j++) { + if (action_items[i].type == KM_KBP_IT_BACK || action_items[i].type == KM_KBP_IT_CHAR || action_items[i].type == KM_KBP_IT_EMIT_KEYSTROKE) { + return FALSE; + } + } + return TRUE; +} + +static gboolean +ibus_keyman_engine_process_key_event (IBusEngine *engine, + guint keyval, + guint keycode, + guint state) +{ + IBusKeymanEngine *keyman = (IBusKeymanEngine *) engine; + + g_message("DAR: ibus_keyman_engine_process_key_event - keyval=%02i, keycode=%02i, state=%02x", keyval, keycode, state); + + if (state & IBUS_RELEASE_MASK) + { + switch(keycode) { + case KEYMAN_LCTRL: + keyman->lctrl_pressed = FALSE; + break; + case KEYMAN_RCTRL: + keyman->rctrl_pressed = FALSE; + break; + case KEYMAN_LALT: + keyman->lalt_pressed = FALSE; + break; + case KEYMAN_RALT: + keyman->ralt_pressed = FALSE; + break; + default: + break; + } + return FALSE; + } + + if (keycode < 0 || keycode > 255) + { + g_warning("keycode %d out of range", keycode); + return FALSE; + } + + if (keycode_to_vk[keycode] == 0) // key we don't handle + { + //save if a possible Ctrl or Alt modifier + switch(keycode) { + case KEYMAN_LCTRL: + keyman->lctrl_pressed = TRUE; + break; + case KEYMAN_RCTRL: + keyman->rctrl_pressed = TRUE; + break; + case KEYMAN_LALT: + keyman->lalt_pressed = TRUE; + break; + case KEYMAN_RALT: + keyman->ralt_pressed = TRUE; + break; + default: + break; + } + return FALSE; + } + + // keyman modifiers are different from X11/ibus + uint16_t km_mod_state = 0; + if (state & IBUS_SHIFT_MASK) + { + km_mod_state |= KM_KBP_MODIFIER_SHIFT; + } + if (state & IBUS_MOD5_MASK) + { + km_mod_state |= KM_KBP_MODIFIER_RALT; + g_message("modstate KM_KBP_MODIFIER_RALT from IBUS_MOD5_MASK"); + } + if (state & IBUS_MOD1_MASK) + { + if (keyman->ralt_pressed) { + km_mod_state |= KM_KBP_MODIFIER_RALT; + g_message("modstate KM_KBP_MODIFIER_RALT from ralt_pressed"); + } + if (keyman->lalt_pressed) { + km_mod_state |= KM_KBP_MODIFIER_LALT; + g_message("modstate KM_KBP_MODIFIER_LALT from lalt_pressed"); + } + } + if (state & IBUS_CONTROL_MASK) + { + if (keyman->rctrl_pressed) { + km_mod_state |= KM_KBP_MODIFIER_RCTRL; + g_message("modstate KM_KBP_MODIFIER_RCTRL from rctrl_pressed"); + } + if (keyman->lctrl_pressed) { + km_mod_state |= KM_KBP_MODIFIER_LCTRL; + g_message("modstate KM_KBP_MODIFIER_LCTRL from lctrl_pressed"); + } + } + g_message("before process key event"); + km_kbp_context *context = km_kbp_state_context(keyman->state); + g_free(get_current_context_text(context)); + g_message("DAR: ibus_keyman_engine_process_key_event - km_mod_state=%x", km_mod_state); + km_kbp_status event_status = km_kbp_process_event(keyman->state, + keycode_to_vk[keycode], km_mod_state); + context = km_kbp_state_context(keyman->state); + g_message("after process key event"); + g_free(get_current_context_text(context)); + + // km_kbp_state_action_items to get action items + size_t num_action_items; + gint numbytes; + g_free(keyman->char_buffer); + keyman->char_buffer = NULL; + const km_kbp_action_item *action_items = km_kbp_state_action_items(keyman->state, + &num_action_items); + + for (int i = 0; i < num_action_items; i++) + { + switch(action_items[i].type) + { + case KM_KBP_IT_CHAR: + g_message("CHAR action %d/%d", i+1, (int)num_action_items); + if (g_unichar_type(action_items[i].character) == G_UNICODE_SURROGATE) { + if (keyman->firstsurrogate == 0) { + keyman->firstsurrogate = action_items[i].character; + g_message("first surrogate %d", keyman->firstsurrogate); + } + else { + glong items_read, items_written; + gunichar2 utf16_pair[2] = {keyman->firstsurrogate, action_items[i].character}; + gchar *utf8_pair = g_utf16_to_utf8 (utf16_pair, 2, + &items_read, + &items_written, + NULL); + if (keyman->char_buffer == NULL) { + keyman->char_buffer = utf8_pair; + } + else { + gchar *new_buffer = g_strjoin("", keyman->char_buffer, utf8_pair, NULL); + g_free(keyman->char_buffer); + g_free(utf8_pair); + keyman->char_buffer = new_buffer; + } + keyman->firstsurrogate = 0; + } + } + else { + gchar *utf8 = (gchar *) g_new0(gchar, 12); + numbytes = g_unichar_to_utf8(action_items[i].character, utf8); + if (numbytes > 12) { + g_error("g_unichar_to_utf8 overflowing buffer"); + g_free(utf8); + } + else { + g_message("unichar:U+%04x, bytes:%d, string:%s", action_items[i].character, numbytes, utf8); + if (keyman->char_buffer == NULL) { + g_message("setting buffer to converted unichar"); + keyman->char_buffer = utf8; + } + else { + g_message("appending converted unichar to CHAR buffer"); + gchar *new_buffer = g_strjoin("", keyman->char_buffer, utf8, NULL); + g_free(keyman->char_buffer); + g_free(utf8); + keyman->char_buffer = new_buffer; + } + g_message("CHAR buffer is now %s", keyman->char_buffer); + } + } + break; + case KM_KBP_IT_MARKER: + g_message("MARKER action %d/%d", i+1, (int)num_action_items); + break; + case KM_KBP_IT_ALERT: + g_message("ALERT action %d/%d", i+1, (int)num_action_items); + GdkDisplay *display = gdk_display_open(NULL); + if (display != NULL) { + gdk_display_beep(display); + gdk_display_close(display); + } + break; + case KM_KBP_IT_BACK: + g_message("BACK action %d/%d", i+1, (int)num_action_items); + if (keyman->char_buffer != NULL) + { + // ibus_keyman_engine_commit_string(keyman, keyman->char_buffer); + g_message("removing one utf8 char from CHAR buffer"); + glong end_pos = g_utf8_strlen(keyman->char_buffer, -1); + gchar *new_buffer; + if (end_pos == 1) { + new_buffer = NULL; + g_message("resetting CHAR buffer to NULL"); + } + else { + new_buffer = g_utf8_substring(keyman->char_buffer, 0 , end_pos - 1); + g_message("changing CHAR buffer to :%s:", new_buffer); + } + if (g_strcmp0(keyman->char_buffer, new_buffer) == 0) { + g_message("oops, CHAR buffer hasn't changed"); + } + g_free(keyman->char_buffer); + keyman->char_buffer = new_buffer; + } + else if (ok_for_single_backspace(action_items, i, num_action_items)) { + // single backspace can be handled by ibus as normal + g_message("no char actions, just single back"); + return FALSE; + } + else { + g_message("DAR: ibus_keyman_engine_process_key_event - client_capabilities=%x, %x", engine->client_capabilities, IBUS_CAP_SURROUNDING_TEXT); + + if ((engine->client_capabilities & IBUS_CAP_SURROUNDING_TEXT) != 0) { + g_message("deleting surrounding text 1 char"); + ibus_engine_delete_surrounding_text(engine, -1, 1); + } else { + g_message("forwarding backspace with reset context"); + km_kbp_context_item *context_items; + km_kbp_context_get(km_kbp_state_context(keyman->state), + &context_items); + reset_context(engine); + forward_backspace(keyman, 0); + km_kbp_context_set(km_kbp_state_context(keyman->state), + context_items); + km_kbp_context_items_dispose(context_items); + } + } + break; + case KM_KBP_IT_PERSIST_OPT: + g_message("PERSIST_OPT action %d/%d", i+1, (int)num_action_items); + break; + case KM_KBP_IT_EMIT_KEYSTROKE: + if (keyman->char_buffer != NULL) + { + ibus_keyman_engine_commit_string(keyman, keyman->char_buffer); + g_free(keyman->char_buffer); + keyman->char_buffer = NULL; + } + g_message("EMIT_KEYSTROKE action %d/%d", i+1, (int)num_action_items); + keyman->emitting_keystroke = TRUE; + break; + case KM_KBP_IT_INVALIDATE_CONTEXT: + g_message("INVALIDATE_CONTEXT action %d/%d", i+1, (int)num_action_items); + km_kbp_context_clear(km_kbp_state_context(keyman->state)); + reset_context(engine); + break; + case KM_KBP_IT_END: + g_message("END action %d/%d", i+1, (int)num_action_items); + keyman->firstsurrogate = 0; + if (keyman->char_buffer != NULL) + { + ibus_keyman_engine_commit_string(keyman, keyman->char_buffer); + g_free(keyman->char_buffer); + keyman->char_buffer = NULL; + } + if (keyman->emitting_keystroke) { + keyman->emitting_keystroke = FALSE; + return FALSE; + } + break; + default: + g_warning("Unknown action %d/%d(%d)", i+1, (int)num_action_items, action_items[i].type); + } + } + context = km_kbp_state_context(keyman->state); + g_message("after processing all actions"); + g_free(get_current_context_text(context)); + return TRUE; + } + +static void +ibus_keyman_engine_set_surrounding_text (IBusEngine *engine, + IBusText *text, + guint cursor_pos, + guint anchor_pos) +{ + gchar *surrounding_text; + guint context_start = cursor_pos > MAXCONTEXT_ITEMS ? cursor_pos - MAXCONTEXT_ITEMS : 0; + g_message("ibus_keyman_engine_set_surrounding_text"); + if (cursor_pos != anchor_pos){ + g_message("ibus_keyman_engine_set_surrounding_text: There is a selection"); + } + parent_class->set_surrounding_text (engine, text, cursor_pos, anchor_pos); + surrounding_text = g_utf8_substring(ibus_text_get_text(text), context_start, cursor_pos); + g_message("surrounding context is:%u:%s:", cursor_pos - context_start, surrounding_text); + g_free(surrounding_text); + reset_context(engine); +} + +// static void ibus_keyman_engine_set_cursor_location (IBusEngine *engine, +// gint x, +// gint y, +// gint w, +// gint h) +// { +// g_message("ibus_keyman_engine_set_cursor_location"); +// //ibus_keyman_engine_reset(engine); +// parent_class->set_cursor_location (engine, x, y, w, h); +// } + +static void +ibus_keyman_engine_focus_in (IBusEngine *engine) +{ + IBusKeymanEngine *keyman = (IBusKeymanEngine *) engine; + + g_message("ibus_keyman_engine_focus_in"); + ibus_engine_register_properties (engine, keyman->prop_list); + + reset_context(engine); + parent_class->focus_in (engine); +} + +static void +ibus_keyman_engine_focus_out (IBusEngine *engine) +{ + IBusKeymanEngine *keyman = (IBusKeymanEngine *) engine; + + g_message("ibus_keyman_engine_focus_out"); + km_kbp_context_clear(km_kbp_state_context(keyman->state)); + parent_class->focus_out (engine); +} + +static void +ibus_keyman_engine_reset (IBusEngine *engine) +{ + g_message("ibus_keyman_engine_reset"); + parent_class->reset (engine); + ibus_keyman_engine_focus_in (engine); +} + + + +static void +ibus_keyman_engine_enable (IBusEngine *engine) +{ + const gchar *engine_name; + IBusKeymanEngine *keyman = (IBusKeymanEngine *) engine; + + engine_name = ibus_engine_get_name (engine); + g_assert (engine_name); + g_message("WDG: ibus_keyman_engine_enable %s", engine_name); + g_message("enabling surrounding context"); + ibus_engine_get_surrounding_text(engine, NULL, NULL, NULL); + if (keyman->ldmlfile) + { + // own dbus name com.Keyman + // expose properties LDMLFile and Name + KeymanService *service = km_service_get_default(); + km_service_set_ldmlfile (service, keyman->ldmlfile); + km_service_set_name (service, keyman->kb_name); + } + parent_class->enable (engine); +} + +static void +ibus_keyman_engine_disable (IBusEngine *engine) +{ + const gchar *engine_name; + + engine_name = ibus_engine_get_name (engine); + g_assert (engine_name); + g_message("WDG: ibus_keyman_engine_disable %s", engine_name); + ibus_keyman_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); +} + +// static void +// ibus_keyman_engine_page_up (IBusEngine *engine) +// { +// g_message("ibus_keyman_engine_page_up"); +// parent_class->page_up (engine); +// reset_context(engine); +// } + +// static void +// ibus_keyman_engine_page_down (IBusEngine *engine) +// { +// g_message("ibus_keyman_engine_page_down"); +// parent_class->page_down (engine); +// reset_context(engine); +// } + +// static void +// ibus_keyman_engine_cursor_up (IBusEngine *engine) +// { +// g_message("ibus_keyman_engine_cursor_up"); +// parent_class->cursor_up (engine); +// reset_context(engine); +// } + +// static void +// ibus_keyman_engine_cursor_down (IBusEngine *engine) +// { +// g_message("ibus_keyman_engine_cursor_down"); +// parent_class->cursor_down (engine); +// reset_context(engine); +// } + +static void +ibus_keyman_engine_property_activate (IBusEngine *engine, + const gchar *prop_name, + guint prop_state) +{ + g_message("ibus_keyman_engine_property_activate"); + parent_class->property_activate (engine, prop_name, prop_state); +} + diff --git a/src/engine.h b/src/engine.h new file mode 100644 index 0000000..88d1b2a --- /dev/null +++ b/src/engine.h @@ -0,0 +1,34 @@ +/* vim:set et sts=4: */ + +/* + * Keyman 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 + * + */ + +#ifndef __ENGINE_H__ +#define __ENGINE_H__ + +#include <ibus.h> + +#define IBUS_TYPE_KEYMAN_ENGINE \ + (ibus_keyman_engine_get_type ()) + +GType ibus_keyman_engine_get_type (void); + +#endif diff --git a/src/keyman-service.c b/src/keyman-service.c new file mode 100644 index 0000000..d997a29 --- /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 3 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..d71def1 --- /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 3 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/keyman.xml.in b/src/keyman.xml.in new file mode 100644 index 0000000..e2b17e3 --- /dev/null +++ b/src/keyman.xml.in @@ -0,0 +1,18 @@ +<?xml version=\"1.0\" encoding=\"utf-8\"?> +<!-- filename: keyman.xml --> +<component> + <name>org.freedesktop.IBus.Keyman</name> + <description>Keyman Component</description> + <exec>${libexecdir}/ibus-engine-keyman --ibus</exec> + <version>11.0.103</version> + <author>Daniel Glassey <wdg@debian.org></author> + <license>GPL</license> + <homepage>http://www.keyman.com</homepage> + <textdomain>ibus-keyman</textdomain> + <observed-paths> + <path>/usr/share/keyman/</path> + <path>/usr/local/share/keyman/</path> + <path>~/.local/share/keyman/</path> + </observed-paths> + <engines exec=\"${libexecdir}/ibus-engine-keyman --xml\" /> +</component> diff --git a/src/keyman.xml.in.in b/src/keyman.xml.in.in new file mode 100644 index 0000000..48fd439 --- /dev/null +++ b/src/keyman.xml.in.in @@ -0,0 +1,18 @@ +<?xml version=\"1.0\" encoding=\"utf-8\"?> +<!-- filename: keyman.xml --> +<component> + <name>org.freedesktop.IBus.Keyman</name> + <description>Keyman Component</description> + <exec>${libexecdir}/ibus-engine-keyman --ibus</exec> + <version>@VERSION@</version> + <author>Daniel Glassey <wdg@debian.org></author> + <license>GPL</license> + <homepage>http://www.keyman.com</homepage> + <textdomain>ibus-keyman</textdomain> + <observed-paths> + <path>/usr/share/keyman/</path> + <path>/usr/local/share/keyman/</path> + <path>~/.local/share/keyman/</path> + </observed-paths> + <engines exec=\"${libexecdir}/ibus-engine-keyman --xml\" /> +</component> diff --git a/src/keymanutil.c b/src/keymanutil.c new file mode 100644 index 0000000..9f2734b --- /dev/null +++ b/src/keymanutil.c @@ -0,0 +1,328 @@ +/* vim:set et sts=4: */ + +/* + * Keyman Input Method for IBUS (The Input Bus) + * + * Copyright (C) 2018 SIL International + * + * keymanutil 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include <stdlib.h> +#include <dirent.h> +#include <sys/stat.h> +#include <glib.h> +#include <glib/gprintf.h> +#include <string.h> + + +#include "keymanutil.h" +#include "kmpdetails.h" + +#define N_(text) text + +// change to keyman_get_kmpdirs_fromdir +// returns list of directories with kmp.json +GList * keyman_get_kmpdirs_fromdir( GList *keyboard_list, const gchar * path) +{ + DIR *dir = opendir(path); + + if (dir != NULL) { + struct dirent *file = readdir(dir); + while (file != NULL) { + struct stat filestat; + gchar * absfn = g_strdup_printf("%s/%s", path, file->d_name); + stat(absfn, &filestat); + + if (S_ISDIR(filestat.st_mode)) + { + if(g_strcmp0(file->d_name, ".") != 0 && g_strcmp0(file->d_name, "..") != 0) + keyboard_list = keyman_get_kmpdirs_fromdir(keyboard_list, absfn); + } + // Looking for kmp.json + else if (S_ISREG(filestat.st_mode) && g_strcmp0(file->d_name, "kmp.json") == 0) + { + g_message("adding kmp path %s", path); + keyboard_list=g_list_append(keyboard_list, g_strdup(path)); + } + g_free(absfn); + + file = readdir(dir); + } + closedir(dir); + } + return keyboard_list; +} + +gchar * keyman_get_icon_file(const gchar *kmx_file) +{ + // Now there will only be the .png + // which at some point will get extracted from the .kmx during installation + gchar *filename, *full_path_to_icon_file, *p; + + p=rindex(kmx_file,'.'); + filename = g_strndup(kmx_file, p-kmx_file); + full_path_to_icon_file=g_strdup_printf("%s.ico.png", filename); + g_free(filename); + + if (!g_file_test(full_path_to_icon_file, G_FILE_TEST_EXISTS)) { + g_free(full_path_to_icon_file); + full_path_to_icon_file=g_strdup("/usr/share/keyman/icons/default.png"); + } + return full_path_to_icon_file; +} + +static IBusEngineDesc * +ibus_keyman_engine_desc_new (gchar * file_name, + gchar *name, + gchar *description, + gchar *copyright, + gchar *lang, + gchar *license, + gchar *author, + gchar *icon, + gchar *layout, + gchar *version) +{ + IBusEngineDesc *engine_desc; + gchar * desc; + + if (description == NULL) { + desc = g_strdup_printf("%s", copyright); + } + else { + desc = g_strdup_printf("%s\n%s", description, copyright); + } + + engine_desc = ibus_engine_desc_new_varargs ("name", file_name, + "longname", name, + "description", desc, + "language", lang ? lang : "other", + "license", license ? license : "", + "author", author ? author : "", + "icon", icon, + "layout", layout, + "version", version ? version : "", + NULL); + g_free(desc); + + return engine_desc; +} + +GList * +ibus_keyman_add_engines(GList * engines, GList * kmpdir_list) +{ + GList *p, *k, *l, *e; + + for (p=kmpdir_list; p != NULL; p = p->next) { + gchar * kmp_dir = (gchar *) p->data; + + kmp_details *details = g_new0(kmp_details, 1); + get_kmp_details(kmp_dir, details); + + for (k=details->keyboards; k != NULL; k = k->next) { + gchar *lang=NULL; + gchar *name_with_lang = NULL; + kmp_keyboard *keyboard = (kmp_keyboard *) k->data; + gboolean alreadyexists = FALSE; + + for (e=engines; e != NULL && alreadyexists == FALSE; e = e->next) { + IBusEngineDesc *engine_desc = (IBusEngineDesc *) e->data; + const gchar *version = ibus_engine_desc_get_version(engine_desc); + const gchar *engine_name = ibus_engine_desc_get_version(engine_desc); + gchar *kmx_file = g_path_get_basename(engine_name); + if (g_strcmp0(kmx_file, keyboard->kmx_file) == 0 && g_strcmp0(version, keyboard->version) >= 0) { + alreadyexists = TRUE; + g_debug("keyboard %s already exists at version %s which is newer or same as %s", kmx_file, version, keyboard->version); + } + g_free(kmx_file); + } + + if (!alreadyexists) { + gchar *abs_kmx = g_strjoin("/", kmp_dir, keyboard->kmx_file, NULL); + gchar *json_file = g_strjoin(".", keyboard->id, "json", NULL); + keyboard_details *kbd_details = g_new0(keyboard_details, 1); + get_keyboard_details(kmp_dir, json_file, kbd_details); + g_free(json_file); + + if (keyboard->languages != NULL) { + for (l=keyboard->languages; l != NULL; l = l->next) { + kmp_language *language = (kmp_language *) l->data; + if (language->id != NULL) { + gchar **tagparts = g_strsplit(language->id, "-", 2); + lang = g_strdup(tagparts[0]); + g_strfreev(tagparts); + // If ibus doesn't know about the language then append the + // language name to the keyboard name + if (language->name != NULL) { + if (g_strcmp0(ibus_get_untranslated_language_name (lang), "Other") == 0) { + name_with_lang = g_strjoin(" - ", keyboard->name, language->name, NULL); + } + } + + gchar *id_with_lang = g_strjoin(":", language->id, abs_kmx, NULL); + + g_message("adding engine %s", id_with_lang); + engines = g_list_append (engines, + ibus_keyman_engine_desc_new (id_with_lang, // lang:kmx full path + name_with_lang ? name_with_lang : keyboard->name, // longname + kbd_details->description, // description + details->info.copyright, // copyright if available + lang, // language, most are ignored by ibus except major languages + kbd_details->license, // license + details->info.author_desc, // author name only, not email + keyman_get_icon_file(abs_kmx), // icon full path + "us", // layout defaulting to us (en-US) + keyboard->version)); + g_free(lang); + g_free(id_with_lang); + g_free(name_with_lang); + name_with_lang = NULL; + } + } + } + else { + g_message("adding engine %s", abs_kmx); + engines = g_list_append (engines, + ibus_keyman_engine_desc_new (abs_kmx, // kmx full path + keyboard->name, // longname + kbd_details->description, // description + details->info.copyright, // copyright if available + lang, // language, most are ignored by ibus except major languages + kbd_details->license, // license + details->info.author_desc, // author name only, not email + keyman_get_icon_file(abs_kmx), // icon full path + "us", // layout defaulting to us (en-US) + keyboard->version)); + } + free_keyboard_details(kbd_details); + g_free(kbd_details); + g_free(abs_kmx); + } + } + free_kmp_details(details); + g_free(details); + } + return engines; +} + +GList * +ibus_keyman_list_engines (void) +{ + GList *engines = NULL; + GList *keyboard_list; + gchar *local_keyboard_path, *xdgenv; + + g_debug("adding from /usr/share/keyman"); + keyboard_list = keyman_get_kmpdirs_fromdir(NULL, "/usr/share/keyman"); + g_debug("adding from /usr/local/share/keyman"); + keyboard_list = keyman_get_kmpdirs_fromdir(keyboard_list, "/usr/local/share/keyman"); + xdgenv = getenv("XDG_DATA_HOME"); + if (xdgenv != NULL){ + local_keyboard_path= g_strdup_printf("%s/keyman", xdgenv); + } + else { + xdgenv = getenv("HOME"); + local_keyboard_path= g_strdup_printf("%s/.local/share/keyman", xdgenv); + } + g_debug("adding from %s", local_keyboard_path); + keyboard_list = keyman_get_kmpdirs_fromdir(keyboard_list, local_keyboard_path); + g_free(local_keyboard_path); + engines = ibus_keyman_add_engines(engines, keyboard_list); + g_list_free(keyboard_list); + + return engines; +} + +IBusComponent * +ibus_keyman_get_component (void) +{ + GList *engines, *p; + IBusComponent *component; + + component = ibus_component_new ("org.freedesktop.IBus.Keyman", + N_("Keyman"), + "10.99.0", + "GPL", + "Daniel Glassey <wdg@debian.org>", + "http://www.keyman.com", + "", + "ibus-keyman"); + + engines = ibus_keyman_list_engines (); + + for (p = engines; p != NULL; p = p->next) { + ibus_component_add_engine (component, (IBusEngineDesc *) p->data); + } + + g_list_free (engines); + return component; +} + +#ifdef DEBUG +#include <locale.h> + +int main () +{ + IBusComponent *component; + GString *output; + + setlocale (LC_ALL, ""); + ibus_init (); + + component = ibus_keyman_get_component (); + + output = g_string_new (""); + + ibus_component_output (component, output, 1); + + g_debug ("\n%s", output->str); + + g_string_free (output, TRUE); + g_object_unref (component); + + return 0; +} +#endif + diff --git a/src/keymanutil.h b/src/keymanutil.h new file mode 100644 index 0000000..d2e32fa --- /dev/null +++ b/src/keymanutil.h @@ -0,0 +1,61 @@ +/* vim:set et sts=4: */ + +/* + * Keyman Input Method for IBUS (The Input Bus) + * + * Copyright (C) 2018 SIL International + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#ifndef __KEYMANUTIL_H__ +#define __KEYMANUTIL_H__ + +#include <ibus.h> +#include <keyman/keyboardprocessor.h> + +void ibus_keyman_init (void); +GList *ibus_keyman_list_engines (void); +IBusComponent *ibus_keyman_get_component (void); +#endif diff --git a/src/kmpdetails.c b/src/kmpdetails.c new file mode 100644 index 0000000..3919dc1 --- /dev/null +++ b/src/kmpdetails.c @@ -0,0 +1,476 @@ +/* vim:set et sts=4: */ + +/* + * Keyman Input Method for IBUS (The Input Bus) + * + * Copyright (C) 2018 SIL International + * + * kmpdetails 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + + + +// APIs to get info that ibus-keyman will want from +// the kmp.json from each kmp +// +// get list of keyboards from this +// associated languages + +#include <locale.h> +#include <stdlib.h> +#include <stdio.h> +#include <glib.h> +#include <json-glib/json-glib.h> +#include "kmpdetails.h" + + +void get_detail_description_from_object(JsonObject *object, const gchar *member_name, gchar **description, gchar **url) +{ + const gchar *value; + JsonNode *member_node; + JsonObject *member_object; + + member_node = json_object_get_member(object, member_name); + if (member_node != NULL && JSON_NODE_HOLDS_VALUE (member_node)) { + value = json_object_get_string_member (object, member_name); + *description = g_strdup(value); + if (url != NULL) { + *url = NULL; + } + } + else if (member_node != NULL && JSON_NODE_HOLDS_OBJECT (member_node)) { + member_object = json_node_get_object(member_node); + + member_node = json_object_get_member(member_object, "description"); + if (member_node != NULL && JSON_NODE_HOLDS_VALUE (member_node)) { + value = json_object_get_string_member (member_object, "description"); + *description = g_strdup(value); + } + else { + g_warning("could not find description in %s\n", member_name); + *description = NULL; + if (url != NULL) { + *url = NULL; + } + } + if (url != NULL) { + member_node = json_object_get_member(member_object, "url"); + if (member_node != NULL && JSON_NODE_HOLDS_VALUE (member_node)) { + value = json_object_get_string_member (member_object, "url"); + *url = g_strdup(value); + } + } + } + else { + g_message("could not find %s in json\n", member_name); + *description = NULL; + if (url != NULL) { + *url = NULL; + } + } +} + + +void get_detail_from_object(JsonObject *object, const gchar *member_name, gchar **detail) +{ + const gchar *value; + JsonNode *member_node; + + member_node = json_object_get_member(object, member_name); + if (member_node != NULL && JSON_NODE_HOLDS_VALUE (member_node)) { + value = json_object_get_string_member (object, member_name); + *detail = g_strdup(value); + } + else { + *detail = NULL; + } +} + +void kmp_languages_foreach (JsonArray *array, + guint index_, + JsonNode *element_node, + gpointer user_data) +{ + JsonObject *lang_object; + kmp_keyboard *keyboard = (kmp_keyboard *) user_data; + kmp_language *language = g_new0(kmp_language, 1); + + if (JSON_NODE_HOLDS_OBJECT(element_node)){ + lang_object = json_node_get_object(element_node); + get_detail_from_object(lang_object, "name", + &(language->name)); + get_detail_from_object(lang_object, "id", + &(language->id)); + keyboard->languages = g_list_append(keyboard->languages, language); + } +} + + +void kmp_keyboards_foreach (JsonArray *array, + guint index_, + JsonNode *element_node, + gpointer user_data) +{ + JsonObject *keyboard_object; + JsonNode *languages_node; + GList *l; + gchar *l_kmx_file, *l_kvk_file; + kmp_fileinfo *fileinfo; + kmp_details *details = (kmp_details *) user_data; + kmp_keyboard *keyboard = g_new0(kmp_keyboard, 1); + + if (JSON_NODE_HOLDS_OBJECT(element_node)){ + keyboard_object = json_node_get_object(element_node); + get_detail_from_object(keyboard_object, "name", + &(keyboard->name)); + get_detail_from_object(keyboard_object, "id", + &(keyboard->id)); + get_detail_from_object(keyboard_object, "version", + &(keyboard->version)); + // languages is another array + languages_node = json_object_get_member(keyboard_object, "languages"); + if (languages_node != NULL && JSON_NODE_HOLDS_ARRAY (languages_node)) { + array = json_node_get_array (languages_node); + if (array) + { + json_array_foreach_element (array, + kmp_languages_foreach, + keyboard); + } + } + + if (keyboard->id) + { + l_kmx_file = g_strdup_printf("%s.kmx", keyboard->id); + l_kvk_file = g_strdup_printf("%s.kvk", keyboard->id); + if (details->files != NULL) { + for (l = details->files; l != NULL; l = l->next) { + fileinfo = (kmp_fileinfo *) l->data; + if (g_strcmp0(fileinfo->name, l_kmx_file)) { + keyboard->kmx_file = g_strdup(l_kmx_file); + } + else if (g_strcmp0(fileinfo->name, l_kvk_file)) { + keyboard->kvk_file = g_strdup(l_kvk_file); + } + } + } + g_free(l_kmx_file); + g_free(l_kvk_file); + } + details->keyboards = g_list_append(details->keyboards, keyboard); + } +} + +void kmp_files_foreach (JsonArray *array, + guint index_, + JsonNode *element_node, + gpointer user_data) +{ + JsonObject *file_object; + kmp_details *details = (kmp_details *) user_data; + kmp_fileinfo *fileinfo = g_new0(kmp_fileinfo, 1); + + if (JSON_NODE_HOLDS_OBJECT(element_node)){ + file_object = json_node_get_object(element_node); + get_detail_from_object(file_object, "name", + &(fileinfo->name)); + get_detail_from_object(file_object, "description", + &(fileinfo->description)); + details->files = g_list_append(details->files, fileinfo); + } +} + +kmp_json_status get_keyboard_details(const char *kmp_dir, const char *id, keyboard_details *keyboard) +{ + JsonParser *parser; + JsonObject *object; + JsonNode *root; + const gchar *value = NULL; + gchar *json_file; + GError *error = NULL; + + parser = json_parser_new (); + json_file = g_strjoin("/", kmp_dir, id, NULL); + + if (!g_file_test(json_file, G_FILE_TEST_EXISTS)) { + g_free(json_file); + return JSON_FILE_NOT_EXISTS; + } + + json_parser_load_from_file (parser, + json_file, + &error); + if (error) + { + g_warning ("Unable to parse `%s': %s\n", json_file, error->message); + g_free(json_file); + g_error_free (error); + g_object_unref (parser); + return JSON_PARSE_ERROR; + } + g_free(json_file); + + root = json_parser_get_root (parser); + + if (JSON_NODE_HOLDS_OBJECT(root)){ + object = json_node_get_object(root); + get_detail_from_object(object, "id", + &(keyboard->id)); + get_detail_from_object(object, "description", + &(keyboard->description)); + get_detail_from_object(object, "license", + &(keyboard->license)); + } + g_object_unref(parser); + return JSON_OK; + + + +} + +kmp_json_status get_kmp_details(const char *kmp_dir, kmp_details *details) +{ + JsonParser *parser; + JsonNode *root, *member_node; + JsonObject *root_object, *object; + JsonArray *array; + JsonNode *kmp_system, *kmp_info, *kmp_options, *kmp_files, *kmp_keyboards; + const gchar *value = NULL; + gchar *kmp_json; + GError *error = NULL; + + parser = json_parser_new (); + kmp_json = g_strdup_printf("%s/kmp.json", kmp_dir); + + if (!g_file_test(kmp_json, G_FILE_TEST_EXISTS)) { + g_free(kmp_json); + return JSON_FILE_NOT_EXISTS; + } + + + json_parser_load_from_file (parser, + kmp_json, + &error); + if (error) + { + g_warning ("Unable to parse `%s': %s\n", kmp_json, error->message); + g_free(kmp_json); + g_error_free (error); + g_object_unref (parser); + return JSON_PARSE_ERROR; + } + g_free(kmp_json); + + root = json_parser_get_root (parser); + + if (JSON_NODE_HOLDS_OBJECT(root)){ + root_object = json_node_get_object(root); + kmp_system = json_object_get_member(root_object, "system"); + if (kmp_system) + { + object = json_node_get_object(kmp_system); + get_detail_from_object(object, "keymanDeveloperVersion", + &(details->system.keymanDeveloperVersion)); + get_detail_from_object(object, "fileVersion", + &(details->system.fileVersion)); + } + + kmp_info = json_object_get_member(root_object, "info"); + if (kmp_info) + { + object = json_node_get_object(kmp_info); + get_detail_description_from_object(object, "name", + &(details->info.name), NULL); + get_detail_description_from_object(object, "version", + &(details->info.version), NULL); + get_detail_description_from_object(object, "copyright", + &(details->info.copyright), NULL); + get_detail_description_from_object(object, "author", + &(details->info.author_desc), &(details->info.author_url)); + get_detail_description_from_object(object, "website", + &(details->info.website_desc), &(details->info.website_url)); + } + + kmp_options = json_object_get_member(root_object, "options"); + if (kmp_options) + { + object = json_node_get_object(kmp_options); + get_detail_from_object(object, "readmeFile", + &(details->options.readmeFile)); + get_detail_from_object(object, "graphicFile", + &(details->options.graphicFile)); + } + + kmp_files = json_object_get_member(root_object, "files"); + details->files = NULL; + if (kmp_files) { + array = json_node_get_array (kmp_files); + if (array) + { + json_array_foreach_element (array, + kmp_files_foreach, + details); + } + } + + kmp_keyboards = json_object_get_member(root_object, "keyboards"); + details->keyboards = NULL; + if (kmp_keyboards) { + array = json_node_get_array (kmp_keyboards); + if (array) + { + json_array_foreach_element (array, + kmp_keyboards_foreach, + details); + } + } + } + g_object_unref(parser); + return JSON_OK; +} + +kmp_json_status print_kmp_details(kmp_details *details) +{ + GList *l, *p; + kmp_keyboard *keyboard; + kmp_language *language; + kmp_fileinfo *fileinfo; + int i, j; + + g_assert(details != NULL); + g_print("system.fileVersion: %s\n", details->system.fileVersion); + g_print("system.keymanDeveloperVersion: %s\n", details->system.keymanDeveloperVersion); + g_print("options.readmeFile: %s\n", details->options.readmeFile); + g_print("options.graphicFile: %s\n", details->options.graphicFile); + g_print("info.name: %s\n", details->info.name); + g_print("info.version: %s\n", details->info.version); + g_print("info.copyright: %s\n", details->info.copyright); + g_print("info.author_desc: %s\n", details->info.author_desc); + g_print("info.author_url: %s\n", details->info.author_url); + g_print("info.website_desc: %s\n", details->info.website_desc); + g_print("info.website_url: %s\n", details->info.website_url); + if (details->keyboards != NULL) { + for (l = details->keyboards, i=0; l != NULL; l = l->next, i++) { + keyboard = (kmp_keyboard *) l->data; + g_print("keyboard.%d.name %s\n", i, keyboard->name); + g_print("keyboard.%d.id %s\n", i, keyboard->id); + g_print("keyboard.%d.version %s\n", i, keyboard->version); + g_print("keyboard.%d.kmx_file %s\n", i, keyboard->kmx_file); + g_print("keyboard.%d.kvk_file %s\n", i, keyboard->kvk_file); + if (keyboard->languages != NULL) { + for (p = keyboard->languages, j=0; p != NULL; p = p->next, j++) { + language = (kmp_language *) p->data; + g_print("keyboard.%d.lang%d.name %s\n", i, j, language->name); + g_print("keyboard.%d.lang%d.id %s\n", i, j, language->id); + } + } + } + } + if (details->files != NULL) { + for (l = details->files, i=0; l != NULL; l = l->next, i++) { + fileinfo = (kmp_fileinfo *) l->data; + g_print("file.%d.name %s\n", i, fileinfo->name); + g_print("file.%d.description %s\n", i, fileinfo->description); + } + } + return JSON_OK; +} + +void free_language(gpointer data) +{ + kmp_language *language = (kmp_language *) data; + g_free(language->name); + g_free(language->id); +} + +void free_keyboard(gpointer data) +{ + kmp_keyboard *keyboard = (kmp_keyboard *) data; + g_free(keyboard->name); + g_free(keyboard->id); + g_free(keyboard->version); + g_free(keyboard->kmx_file); + g_free(keyboard->kvk_file); + if (keyboard->languages != NULL) { + g_list_free_full(keyboard->languages, (GDestroyNotify)free_language); + } +} + +void free_fileinfo(gpointer data) +{ + kmp_fileinfo *fileinfo = (kmp_fileinfo *) data; + g_free(fileinfo->name); + g_free(fileinfo->description); +} + +kmp_json_status free_keyboard_details(keyboard_details *kbd_details) +{ + g_free(kbd_details->id); + g_free(kbd_details->description); + g_free(kbd_details->license); + return JSON_OK; +} + +kmp_json_status free_kmp_details(kmp_details * details) +{ + g_assert(details != NULL); + g_free(details->system.fileVersion); + g_free(details->system.keymanDeveloperVersion); + g_free(details->options.readmeFile); + g_free(details->options.graphicFile); + g_free(details->info.name); + g_free(details->info.version); + g_free(details->info.copyright); + g_free(details->info.author_desc); + g_free(details->info.author_url); + g_free(details->info.website_desc); + g_free(details->info.website_url); + if (details->keyboards != NULL) { + g_list_free_full(details->keyboards, (GDestroyNotify)free_keyboard); + } + if (details->files != NULL) { + g_list_free_full(details->files, (GDestroyNotify)free_fileinfo); + } + return JSON_OK; +} diff --git a/src/kmpdetails.h b/src/kmpdetails.h new file mode 100644 index 0000000..3bcf6a9 --- /dev/null +++ b/src/kmpdetails.h @@ -0,0 +1,78 @@ +// kmp details from json + +#include <glib.h> +typedef struct +{ + gchar *fileVersion; + gchar *keymanDeveloperVersion; +} kmp_system; + +typedef struct +{ + gchar *version; + gchar *name; + gchar *copyright; + gchar *author_desc; + gchar *author_url; + gchar *website_desc; + gchar *website_url; +} kmp_info; + + +typedef struct +{ + gchar *readmeFile; + gchar *graphicFile; +} kmp_options; + +typedef struct +{ + gchar *name; + gchar *id; + gchar *version; + gchar *kmx_file; + gchar *kvk_file; + GList *languages; +} kmp_keyboard; + +typedef struct +{ + gchar *name; + gchar *id; +} kmp_language; + +typedef struct +{ + gchar *name; + gchar *description; +} kmp_fileinfo; + +typedef struct +{ + gchar *id; + gchar *description; + gchar *license; +} keyboard_details; + +typedef struct +{ + kmp_system system; + kmp_info info; + kmp_options options; + GList *keyboards; + GList *files; +} kmp_details; + +enum kmp_json_status_codes { + JSON_OK, + JSON_PARSE_ERROR, + JSON_FILE_NOT_EXISTS +}; + +typedef int kmp_json_status; + +kmp_json_status get_kmp_details(const gchar *kmp_dir, kmp_details *details); +kmp_json_status free_kmp_details(kmp_details * details); +kmp_json_status get_keyboard_details(const gchar *kmp_dir, const gchar *id, keyboard_details *details); +kmp_json_status free_keyboard_details(keyboard_details * details); +kmp_json_status print_kmp_details(kmp_details * details);
\ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..2cabd3f --- /dev/null +++ b/src/main.c @@ -0,0 +1,143 @@ +/* vim:set et sts=4: */ + +/* + * Keyman 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 + * + */ + +#include <ibus.h> +#include <locale.h> +#include <stdlib.h> +#include <stdio.h> +#include "keymanutil.h" +#include "engine.h" +#include "keyman-service.h" + +static IBusBus *bus = NULL; +static IBusFactory *factory = NULL; + +/* options */ +static gboolean xml = FALSE; +static gboolean ibus = FALSE; +static gboolean verbose = FALSE; + +static const GOptionEntry entries[] = +{ + { "xml", 'x', 0, G_OPTION_ARG_NONE, &xml, "generate xml for engines", NULL }, + { "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", NULL }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose", NULL }, + { NULL }, +}; + + +static void +ibus_disconnected_cb (IBusBus *bus, + gpointer user_data) +{ + g_debug ("bus disconnected"); + KeymanService *service = km_service_get_default(); + g_clear_object(&service); + + ibus_quit (); +} + + +static void +start_component (void) +{ + GList *engines, *p; + IBusComponent *component; + + ibus_init (); + + bus = ibus_bus_new (); + g_signal_connect (bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL); + + component = ibus_keyman_get_component (); + + factory = ibus_factory_new (ibus_bus_get_connection (bus)); + + engines = ibus_component_get_engines (component); + for (p = engines; p != NULL; p = p->next) { + IBusEngineDesc *engine = (IBusEngineDesc *)p->data; +#if IBUS_CHECK_VERSION(1,3,99) + const gchar *engine_name = ibus_engine_desc_get_name (engine); +#else + const gchar *engine_name = engine->name; +#endif /* !IBUS_CHECK_VERSION(1,3,99) */ + ibus_factory_add_engine (factory, engine_name, IBUS_TYPE_KEYMAN_ENGINE); + } + + if (ibus) { + ibus_bus_request_name (bus, "org.freedesktop.IBus.Keyman", 0); + } + else { + ibus_bus_register_component (bus, component); + } + + g_object_unref (component); + km_service_get_default(); // initialise dbus service + + ibus_main (); +} + +static void +print_engines_xml (void) +{ + IBusComponent *component; + GString *output; + + ibus_init (); + + component = ibus_keyman_get_component (); + output = g_string_new (""); + + ibus_component_output_engines (component, output, 0); + + fprintf (stdout, "%s", output->str); + + g_string_free (output, TRUE); + +} + +int +main (gint argc, gchar **argv) +{ + GError *error = NULL; + GOptionContext *context; + + setlocale (LC_ALL, ""); + + context = g_option_context_new ("- ibus Keyman engine component"); + + g_option_context_add_main_entries (context, entries, "ibus-keyman"); + + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("Option parsing failed: %s\n", error->message); + exit (-1); + } + + if (xml) { + print_engines_xml (); + exit (0); + } + + start_component (); + return 0; +} diff --git a/src/print_kmp.c b/src/print_kmp.c new file mode 100644 index 0000000..e98c45b --- /dev/null +++ b/src/print_kmp.c @@ -0,0 +1,240 @@ +// APIs to get info that ibus-keyman will want from +// the kmp.json from each kmp +// +// get list of keyboards from this +// associated languages + +#include <locale.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/stat.h> +#include <glib.h> +#include <json-glib/json-glib.h> + + +void node_holds(JsonNode *node, const gchar *name) +{ + if (JSON_NODE_HOLDS_OBJECT(node)){ + g_print("%s holds object\n", name); + } + + if (JSON_NODE_HOLDS_ARRAY(node)){ + g_print("%s holds array\n", name); + } + + if (JSON_NODE_HOLDS_VALUE(node)){ + g_print("%s holds value\n", name); + } + + if (JSON_NODE_HOLDS_NULL(node)){ + g_print("%s holds null\n", name); + } +} + +void print_object(JsonObject *object, const gchar *objname) +{ + GList *members, *l; + const gchar *value = NULL; + gchar *modname; + JsonNode *member_node; + JsonObject *member_object; + + g_print("d"); + members = json_object_get_members (object); + for (l = members; l != NULL; l = l->next) + { + gchar *member_name = (gchar *) l->data; + g_print("(member)%s\n", member_name); + member_node = json_object_get_member(object, member_name); + if (member_node != NULL && g_strcmp0(objname, "root") != 0) + { + if (JSON_NODE_HOLDS_VALUE (member_node)) + { + value = json_object_get_string_member (object, member_name); + g_print(" %s:%s\n", member_name, value); + } + else + { + g_print(" __%s\n", member_name); + if (JSON_NODE_HOLDS_OBJECT (member_node)) + { + member_object = json_node_get_object(member_node); + modname = g_strdup_printf(" %s", member_name); + + g_print("(mod)%s\n", modname); + print_object(member_object, modname); + g_free(modname); + } + else + { + g_print("(member node no object)"); + } + } + } + else + { + if (g_strcmp0(objname, "root") != 0) + { + g_print("(!root)"); + } + if (member_node == NULL) + { + g_print("(tip)"); + } + g_print("x %s\n", member_name); + } + } + g_list_free(members); + g_print("z"); +} + +void print_node(JsonNode *node, const gchar *name) +{ + JsonObject *object; + + g_print("\n(node)%s:\n", name); + object = json_node_get_object(node); + print_object(object, name); +} + +void kmp_files_foreach (JsonArray *array, + guint index_, + JsonNode *element_node, + gpointer user_data) +{ + // JsonObject *file_object; + // g_print("kmp_files_foreach:"); + // node_holds(element_node, "files array member"); + gchar *name = g_strdup_printf("File %d", index_); + print_node(element_node, name); + g_free(name); +} + +void kmp_keyboards_foreach (JsonArray *array, + guint index_, + JsonNode *element_node, + gpointer user_data) +{ + // JsonObject *file_object; + // g_print("kmp_files_foreach:"); + // node_holds(element_node, "files array member"); + gchar *name = g_strdup_printf("Keyboard %d", index_); + print_node(element_node, name); + g_free(name); +} + + + +int +main (gint argc, gchar **argv) +{ + struct stat filestat; + JsonParser *parser; + JsonNode *root; + JsonReader *reader; + JsonObject *object; + JsonArray *array; + JsonNode *kmp_system, *kmp_info, *kmp_options, *kmp_files, *kmp_keyboards; + GError *error = NULL; + if (argc < 2) + { + g_print ("Usage: kmpdetails <kmp.json>\n"); + return EXIT_FAILURE; + } + + stat(argv[1], &filestat); + if (!S_ISREG(filestat.st_mode)) + { + g_print ("Usage: kmpdetails <kmp.json>\n"); + return EXIT_FAILURE; + } + + setlocale (LC_ALL, "C.UTF-8"); + + + // // Only .kmx extensions are valid keyboard files + // else if (S_ISREG(filestat.st_mode) + // && (g_str_has_suffix(absfn, ".kmx")/* && keyman_check_keyboard(absfn) == 0*/)) + // { + // keyboard_list=g_list_append(keyboard_list, absfn); + // } + // else + // { + // g_free(absfn); + // } + + parser = json_parser_new (); + + json_parser_load_from_file (parser, + argv[1], + &error); + if (error) + { + g_print ("Unable to parse `%s': %s\n", argv[1], error->message); + g_error_free (error); + g_object_unref (parser); + return EXIT_FAILURE; + } + + root = json_parser_get_root (parser); + node_holds(root, "root"); + + if (JSON_NODE_HOLDS_OBJECT(root)){ + print_node(root, "root"); + object = json_node_get_object(root); + + kmp_system = json_object_get_member(object, "system"); + if (kmp_system) + { + print_node(kmp_system, "system"); + } + kmp_info = json_object_get_member(object, "info"); + if (kmp_info) + { + print_node(kmp_info, "info"); + } + kmp_options = json_object_get_member(object, "options"); + if (kmp_options) + { + print_node(kmp_options, "options"); + } + kmp_files = json_object_get_member(object, "files"); + if (kmp_files) + { + g_print("\nfiles:\n"); + // node_holds(kmp_files, "files"); + array = json_node_get_array (kmp_files); + if (array) + { + g_print("files array:\n"); + json_array_foreach_element (array, + kmp_files_foreach, + NULL); + } + } + kmp_keyboards = json_object_get_member(object, "keyboards"); + if (kmp_keyboards) + { + g_print("\nkeyboards:\n"); + // node_holds(kmp_keyboards, "keyboards"); + array = json_node_get_array (kmp_keyboards); + if (array) + { + g_print("keyboards array:\n"); + json_array_foreach_element (array, + kmp_keyboards_foreach, + NULL); + } + } + } + + // reader = json_reader_new (root); + + // json_reader_read_member (reader, "system"); + // json_reader_read_member (reader, "fileVersion"); + + // g_object_unref(reader); + g_object_unref(parser); + return EXIT_SUCCESS; +} + diff --git a/src/print_kmpdetails.c b/src/print_kmpdetails.c new file mode 100644 index 0000000..6494f35 --- /dev/null +++ b/src/print_kmpdetails.c @@ -0,0 +1,41 @@ +// APIs to get info that ibus-keyman will want from +// the kmp.json from each kmp +// +// get list of keyboards from this +// associated languages + +#include <locale.h> +#include <sys/stat.h> +#include "kmpdetails.h" + + +int +main (gint argc, gchar **argv) +{ + struct stat filestat; + kmp_details details; + + if (argc < 2) + { + g_print ("Usage: kmpdetails <kmp.json>\n"); + g_print ("ERROR: no file specified\n"); + return EXIT_FAILURE; + } + + stat(argv[1], &filestat); + if (!S_ISREG(filestat.st_mode)) + { + g_print ("Usage: kmpdetails <kmp.json>\n"); + g_print ("ERROR: file %s not found\n", argv[1]); + return EXIT_FAILURE; + } + + setlocale (LC_ALL, "C.UTF-8"); + + get_kmp_details(argv[1], &details); + print_kmp_details(&details); + free_kmp_details(&details); + + return EXIT_SUCCESS; +} + diff --git a/src/test/print_kmp.test b/src/test/print_kmp.test new file mode 100755 index 0000000..f7a7551 --- /dev/null +++ b/src/test/print_kmp.test @@ -0,0 +1,2 @@ +#!/bin/sh +./print_kmp $srcdir/test/kmp.json diff --git a/src/test/print_kmpdetails.test b/src/test/print_kmpdetails.test new file mode 100755 index 0000000..2edab43 --- /dev/null +++ b/src/test/print_kmpdetails.test @@ -0,0 +1,2 @@ +#!/bin/sh +./print_kmpdetails $srcdir/test/kmp.json |