diff --git a/autogen.sh b/autogen.sh index 14db0b1..99be006 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,13 +1,27 @@ #!/bin/sh -set -e -set -x - -autopoint -libtoolize --automake --copy -aclocal -I m4 -autoheader -automake --add-missing --copy -autoconf +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +PKG_NAME="ibus-m17n" + +(test -f $srcdir/configure.ac \ + && test -f $srcdir/README ) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level $PKG_NAME directory" + exit 1 +} + +which gnome-autogen.sh || { + echo "You need to install gnome-common from the GNOME CVS" + exit 1 +} + export CFLAGS="-g -O0" export CXXFLAGS="$CFLAGS" -./configure --enable-maintainer-mode $* + +ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4" +REQUIRED_AUTOMAKE_VERSION=1.10 + +. gnome-autogen.sh diff --git a/codereview.settings b/codereview.settings new file mode 100644 index 0000000..71ecbee --- /dev/null +++ b/codereview.settings @@ -0,0 +1,2 @@ +# This file is used by "git cl" to get code review information. +CODE_REVIEW_SERVER: codereview.appspot.com diff --git a/configure.ac b/configure.ac index 4d5ecc7..d9aeb11 100644 --- a/configure.ac +++ b/configure.ac @@ -80,6 +80,7 @@ Makefile ibus-m17n.spec src/Makefile src/m17n.xml.in +src/default.xml.in icons/Makefile m4/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index 07e4432..eaa8bd8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,6 +22,8 @@ AM_CFLAGS = \ @IBUS_CFLAGS@ \ @M17N_CFLAGS@ \ -DPKGDATADIR=\"$(pkgdatadir)\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DSETUPDIR=\"$(setupdir)\" \ $(NULL) AM_LDADD = \ @IBUS_LIBS@ \ @@ -50,41 +52,38 @@ test_m17n_LDADD = \ libexec_PROGRAMS = ibus-engine-m17n ibus-setup-m17n -ibus_engine_m17n_SOURCES = \ +noinst_LIBRARIES = libm17ncommon.a + +libm17ncommon_a_SOURCES = \ m17nutil.c \ m17nutil.h \ + $(NULL) +ibus_engine_m17n_SOURCES = \ main.c \ engine.c \ engine.h \ $(NULL) -ibus_engine_m17n_CFLAGS = \ - @IBUS_CFLAGS@ \ - @M17N_CFLAGS@ \ - -DPKGDATADIR=\"$(pkgdatadir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - $(NULL) ibus_engine_m17n_LDADD = \ + libm17ncommon.a \ @IBUS_LIBS@ \ @M17N_LIBS@ \ $(NULL) setup_DATA = \ ibus-m17n-preferences.ui \ + default.xml \ $(NULL) setupdir = $(pkgdatadir)/setup ibus_setup_m17n_SOURCES = \ - m17nutil.c \ - m17nutil.h \ setup.c \ $(NULL) ibus_setup_m17n_CFLAGS = \ - @IBUS_CFLAGS@ \ - @M17N_CFLAGS@ \ @GTK2_CFLAGS@ \ - -DSETUPDIR=\"$(setupdir)\" \ + $(AM_CFLAGS) \ $(NULL) ibus_setup_m17n_LDADD = \ + libm17ncommon.a \ @IBUS_LIBS@ \ @M17N_LIBS@ \ @GTK2_LIBS@ \ @@ -96,19 +95,31 @@ component_DATA = \ componentdir = @datadir@/ibus/component EXTRA_DIST = \ - m17n.xml.in \ + m17n.xml.in.in \ + default.xml.in \ $(setup_DATA) \ $(NULL) +DISTCLEANFILES = \ + m17n.xml.in \ + default.xml.in \ + $(NULL) + CLEANFILES = \ m17n.xml \ + default.xml \ $(NULL) m17n.xml: m17n.xml.in +default.xml: default.xml.in + +SUFFIXES = .xml.in .xml +.xml.in.xml: $(AM_V_GEN) \ ( \ libexecdir=${libexecdir}; \ pkgdatadir=${pkgdatadir}; \ + setupdir=${setupdir}; \ s=`cat $<`; \ eval "echo \"$${s}\""; \ ) > $@ diff --git a/src/default.xml.in.in b/src/default.xml.in.in new file mode 100644 index 0000000..5c5d67d --- /dev/null +++ b/src/default.xml.in.in @@ -0,0 +1,246 @@ + + + + + + m17n:as:phonetic + 2 + FALSE + + + m17n:bn:inscript + 2 + FALSE + + + m17n:gu:inscript + 2 + FALSE + + + m17n:hi:inscript + 2 + FALSE + + + m17n:kn:kgp + 2 + FALSE + + + m17n:ks:kbd + 2 + FALSE + + + m17n:mai:inscript + 2 + FALSE + + + m17n:ml:inscript + 2 + FALSE + + + m17n:mr:inscript + 2 + FALSE + + + m17n:ne:rom + 2 + FALSE + + + m17n:or:inscript + 2 + FALSE + + + m17n:pa:inscript + 2 + FALSE + + + m17n:sa:harvard-kyoto + 2 + FALSE + + + m17n:sd:inscript + 2 + FALSE + + + m17n:si:wijesekera + 2 + FALSE + + + m17n:ta:tamil99 + 2 + FALSE + + + m17n:te:inscript + 2 + FALSE + + + + m17n:si:samanala + 0 + FALSE + + + + m17n:ja:anthy + 0 + TRUE + + + m17n:zh:cangjie + 0 + TRUE + + + m17n:zh:py-b5 + 0 + TRUE + + + m17n:zh:py-gb + 0 + TRUE + + + m17n:zh:py + 0 + TRUE + + + m17n:zh:quick + 0 + TRUE + + + m17n:zh:tonepy-b5 + 0 + TRUE + + + m17n:zh:tonepy-gb + 0 + TRUE + + + m17n:zh:tonepy + 0 + TRUE + + + m17n:zh:util + 0 + TRUE + + + + m17n:as:* + 1 + FALSE + + + m17n:bn:* + 1 + FALSE + + + m17n:gu:* + 1 + FALSE + + + m17n:hi:* + 1 + FALSE + + + m17n:kn:* + 1 + FALSE + + + m17n:ks:* + 1 + FALSE + + + m17n:mai:* + 1 + FALSE + + + m17n:ml:* + 1 + FALSE + + + m17n:mr:* + 1 + FALSE + + + m17n:ne:* + 1 + FALSE + + + m17n:or:* + 1 + FALSE + + + m17n:pa:* + 1 + FALSE + + + m17n:sa:* + 1 + FALSE + + + m17n:sd:* + 1 + FALSE + + + m17n:si:* + 1 + FALSE + + + m17n:ta:* + 1 + FALSE + + + m17n:te:* + 1 + FALSE + + + + m17n:* + 0 + FALSE + + diff --git a/src/engine.c b/src/engine.c index 260a806..f8e7fe5 100644 --- a/src/engine.c +++ b/src/engine.c @@ -6,6 +6,23 @@ #include "m17nutil.h" #include "engine.h" +/* type module to assign different GType to each engine */ +#define IBUS_TYPE_M17N_TYPE_MODULE (ibus_m17n_type_module_get_type ()) +#define IBUS_M17N_TYPE_MODULE (module) (G_TYPE_CHECK_INSTANCE_CAST (module, IBUS_TYPE_M17N_TYPE_MODULE, IBusM17NTypeModule) + +typedef struct _IBusM17NTypeModule IBusM17NTypeModule; +typedef struct _IBusM17NTypeModuleClass IBusM17NTypeModuleClass; + +struct _IBusM17NTypeModule +{ + GTypeModule parent_instance; +}; + +struct _IBusM17NTypeModuleClass +{ + GTypeModuleClass parent_class; +}; + typedef struct _IBusM17NEngine IBusM17NEngine; typedef struct _IBusM17NEngineClass IBusM17NEngineClass; @@ -18,20 +35,36 @@ struct _IBusM17NEngine { IBusProperty *status_prop; IBusProperty *setup_prop; IBusPropList *prop_list; - gchar *config_section; }; struct _IBusM17NEngineClass { IBusEngineClass parent; + + /* configurations are per class */ + gchar *config_section; + guint preedit_foreground; + guint preedit_background; + gint preedit_underline; + gint lookup_table_orientation; + + MInputMethod *im; }; /* functions prototype */ +static GType + ibus_m17n_type_module_get_type (void); static void ibus_m17n_engine_class_init (IBusM17NEngineClass *klass); -static void ibus_m17n_engine_init (IBusM17NEngine *m17n); +static void ibus_m17n_engine_class_finalize (IBusM17NEngineClass *klass); +static void ibus_m17n_config_value_changed (IBusConfig *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusM17NEngineClass *klass); static GObject* ibus_m17n_engine_constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params); +static void ibus_m17n_engine_init (IBusM17NEngine *m17n); static void ibus_m17n_engine_destroy (IBusM17NEngine *m17n); static gboolean ibus_m17n_engine_process_key_event @@ -77,13 +110,9 @@ static void ibus_m17n_engine_update_lookup_table (IBusM17NEngine *m17n); static IBusEngineClass *parent_class = NULL; -static GHashTable *im_table = NULL; static IBusConfig *config = NULL; -static guint preedit_foreground = INVALID_COLOR; -static guint preedit_background = INVALID_COLOR; -static gint preedit_underline = IBUS_ATTR_UNDERLINE_NONE; -static gint lookup_table_orientation = IBUS_ORIENTATION_SYSTEM; +static IBusM17NTypeModule *module = NULL; void ibus_m17n_init (IBusBus *bus) @@ -92,31 +121,149 @@ ibus_m17n_init (IBusBus *bus) if (config) g_object_ref_sink (config); ibus_m17n_init_common (); + + module = g_object_new (IBUS_TYPE_M17N_TYPE_MODULE, NULL); } -GType -ibus_m17n_engine_get_type (void) +static gboolean +ibus_m17n_type_module_load (GTypeModule *module) +{ + return TRUE; +} + +static void +ibus_m17n_type_module_unload (GTypeModule *module) +{ +} + +static void +ibus_m17n_type_module_class_init (IBusM17NTypeModuleClass *klass) +{ + GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass); + + module_class->load = ibus_m17n_type_module_load; + module_class->unload = ibus_m17n_type_module_unload; +} + +static GType +ibus_m17n_type_module_get_type (void) { static GType type = 0; static const GTypeInfo type_info = { + sizeof (IBusM17NTypeModuleClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_m17n_type_module_class_init, + (GClassFinalizeFunc) NULL, + NULL, + sizeof (IBusM17NTypeModule), + 0, + (GInstanceInitFunc) NULL, + }; + + if (type == 0) { + type = g_type_register_static (G_TYPE_TYPE_MODULE, + "IBusM17NTypeModule", + &type_info, + (GTypeFlags) 0); + } + + return type; +} + +static gboolean +ibus_m17n_scan_engine_name (const gchar *engine_name, + gchar **lang, + gchar **name) +{ + gchar **strv; + + g_return_val_if_fail (g_str_has_prefix (engine_name, "m17n:"), FALSE); + strv = g_strsplit (engine_name, ":", 3); + + if (g_strv_length (strv) != 3) { + g_strfreev (strv); + g_return_val_if_reached (FALSE); + } + + *lang = strv[1]; + *name = strv[2]; + + g_free (strv[0]); + g_free (strv); + + return TRUE; +} + +static gboolean +ibus_m17n_scan_class_name (const gchar *class_name, + gchar **lang, + gchar **name) +{ + gchar *p; + + g_return_val_if_fail (g_str_has_prefix (class_name, "IBusM17N"), FALSE); + g_return_val_if_fail (g_str_has_suffix (class_name, "Engine"), FALSE); + + /* Strip prefix and suffix */ + p = *lang = g_strdup (class_name + 8); + p = g_strrstr (p, "Engine"); + *p = '\0'; + + /* Find the start position of */ + while (g_ascii_islower (*--p) && p > *lang) + ; + g_return_val_if_fail (p > *lang, FALSE); + *name = g_strdup (p); + *p = '\0'; + + *lang[0] = g_ascii_tolower (*lang[0]); + *name[0] = g_ascii_tolower (*name[0]); + + return TRUE; +} + +GType +ibus_m17n_engine_get_type_for_name (const gchar *engine_name) +{ + GType type; + gchar *type_name, *lang = NULL, *name = NULL; + + GTypeInfo type_info = { sizeof (IBusM17NEngineClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ibus_m17n_engine_class_init, - NULL, + (GClassFinalizeFunc)ibus_m17n_engine_class_finalize, NULL, sizeof (IBusM17NEngine), 0, (GInstanceInitFunc) ibus_m17n_engine_init, }; + if (!ibus_m17n_scan_engine_name (engine_name, &lang, &name)) { + g_free (lang); + g_free (name); + return G_TYPE_INVALID; + } + lang[0] = g_ascii_toupper (lang[0]); + name[0] = g_ascii_toupper (name[0]); + type_name = g_strdup_printf ("IBusM17N%s%sEngine", lang, name); + g_free (lang); + g_free (name); + + type = g_type_from_name (type_name); + g_assert (type == 0 || g_type_is_a (type, IBUS_TYPE_ENGINE)); + if (type == 0) { - type = g_type_register_static (IBUS_TYPE_ENGINE, - "IBusM17NEngine", - &type_info, - (GTypeFlags) 0); + type = g_type_module_register_type (G_TYPE_MODULE (module), + IBUS_TYPE_ENGINE, + type_name, + &type_info, + (GTypeFlags) 0); } + g_free (type_name); return type; } @@ -127,8 +274,12 @@ ibus_m17n_engine_class_init (IBusM17NEngineClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); IBusEngineClass *engine_class = IBUS_ENGINE_CLASS (klass); + GValue value = { 0 }; + gchar *engine_name, *lang = NULL, *name = NULL; + IBusM17NEngineConfig *engine_config; - parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass); + if (parent_class == NULL) + parent_class = (IBusEngineClass *) g_type_class_peek_parent (klass); object_class->constructor = ibus_m17n_engine_constructor; ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_m17n_engine_destroy; @@ -149,50 +300,117 @@ ibus_m17n_engine_class_init (IBusM17NEngineClass *klass) engine_class->cursor_down = ibus_m17n_engine_cursor_down; engine_class->property_activate = ibus_m17n_engine_property_activate; + + if (!ibus_m17n_scan_class_name (G_OBJECT_CLASS_NAME (klass), + &lang, &name)) { + g_free (lang); + g_free (name); + return; + } + engine_name = g_strdup_printf ("m17n:%s:%s", lang, name); + klass->config_section = g_strdup_printf ("engine/M17N/%s/%s", lang, name); + g_free (lang); + g_free (name); + + /* configurations are per class */ + klass->preedit_foreground = INVALID_COLOR; + klass->preedit_background = INVALID_COLOR; + klass->preedit_underline = IBUS_ATTR_UNDERLINE_NONE; + klass->lookup_table_orientation = IBUS_ORIENTATION_SYSTEM; + + engine_config = ibus_m17n_get_engine_config (engine_name); + g_free (engine_name); + + if (ibus_config_get_value (config, + klass->config_section, + "preedit_foreground", + &value)) { + const gchar *hex = g_value_get_string (&value); + + klass->preedit_foreground = ibus_m17n_parse_color (hex); + g_value_unset (&value); + } else if (engine_config->preedit_highlight) + klass->preedit_foreground = PREEDIT_FOREGROUND; + + if (ibus_config_get_value (config, + klass->config_section, + "preedit_background", + &value)) { + const gchar *hex = g_value_get_string (&value); + + klass->preedit_background = ibus_m17n_parse_color (hex); + g_value_unset (&value); + } else if (engine_config->preedit_highlight) + klass->preedit_background = PREEDIT_BACKGROUND; + + if (ibus_config_get_value (config, + klass->config_section, + "preedit_underline", + &value)) { + klass->preedit_underline = g_value_get_int (&value); + g_value_unset (&value); + } else + klass->preedit_underline = IBUS_ATTR_UNDERLINE_NONE; + + if (ibus_config_get_value (config, + klass->config_section, + "lookup_table_orientation", + &value)) { + klass->lookup_table_orientation = g_value_get_int (&value); + g_value_unset (&value); + } else + klass->lookup_table_orientation = IBUS_ORIENTATION_SYSTEM; + + g_signal_connect (config, "value-changed", + G_CALLBACK(ibus_m17n_config_value_changed), + klass); + + klass->im = NULL; } static void -ibus_config_value_changed (IBusConfig *config, - const gchar *section, - const gchar *name, - GValue *value, - gpointer user_data) +ibus_m17n_config_value_changed (IBusConfig *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusM17NEngineClass *klass) { - IBusM17NEngine *m17n = (IBusM17NEngine *) user_data; - - if (g_strcmp0 (section, m17n->config_section) == 0) { + if (g_strcmp0 (section, klass->config_section) == 0) { if (g_strcmp0 (name, "preedit_foreground") == 0) { const gchar *hex = g_value_get_string (value); guint color; color = ibus_m17n_parse_color (hex); if (color != INVALID_COLOR) { - preedit_foreground = color; - ibus_m17n_engine_update_preedit (m17n); + klass->preedit_foreground = color; } } else if (g_strcmp0 (name, "preedit_background") == 0) { const gchar *hex = g_value_get_string (value); guint color; color = ibus_m17n_parse_color (hex); if (color != INVALID_COLOR) { - preedit_background = color; - ibus_m17n_engine_update_preedit (m17n); + klass->preedit_background = color; } } else if (g_strcmp0 (name, "preedit_underline") == 0) { - preedit_underline = g_value_get_int (value); - ibus_m17n_engine_update_preedit (m17n); + klass->preedit_underline = g_value_get_int (value); } else if (g_strcmp0 (name, "lookup_table_orientation") == 0) { - lookup_table_orientation = g_value_get_int (value); - ibus_m17n_engine_update_lookup_table (m17n); + klass->lookup_table_orientation = g_value_get_int (value); } } } static void +ibus_m17n_engine_class_finalize (IBusM17NEngineClass *klass) +{ + if (klass->im) + minput_close_im (klass->im); + g_free (klass->config_section); +} + +static void ibus_m17n_engine_init (IBusM17NEngine *m17n) { IBusText* label; IBusText* tooltip; - const gchar *engine_name; m17n->status_prop = ibus_property_new ("status", PROP_TYPE_NORMAL, @@ -234,123 +452,60 @@ ibus_m17n_engine_constructor (GType type, GObjectConstructParam *construct_params) { IBusM17NEngine *m17n; - MInputMethod *im; - const gchar *engine_name; - gchar *lang; - gchar *name; - gchar **strv; - GValue value = { 0 }; - gboolean preedit_highlight; + GObjectClass *object_class; + IBusM17NEngineClass *klass; m17n = (IBusM17NEngine *) G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_params, construct_params); - engine_name = ibus_engine_get_name ((IBusEngine *) m17n); - g_assert (engine_name); - - strv = g_strsplit (engine_name, ":", 3); + object_class = G_OBJECT_GET_CLASS (m17n); + klass = (IBusM17NEngineClass *) object_class; + if (klass->im == NULL) { + const gchar *engine_name; + gchar *lang = NULL, *name = NULL; - g_assert (g_strv_length (strv) == 3); - g_assert (g_strcmp0 (strv[0], "m17n") == 0); - - lang = strv[1]; - name = strv[2]; - - if (im_table == NULL) { - im_table = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) minput_close_im); - } - - im = (MInputMethod *) g_hash_table_lookup (im_table, engine_name); - if (im == NULL) { - im = minput_open_im (msymbol (lang), msymbol (name), NULL); - if (im != NULL) { - mplist_put (im->driver.callback_list, Minput_preedit_start, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_preedit_draw, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_preedit_done, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_status_start, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_status_draw, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_status_done, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_candidates_start, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_candidates_draw, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_candidates_done, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_set_spot, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_toggle, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_reset, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_get_surrounding_text, ibus_m17n_engine_callback); - mplist_put (im->driver.callback_list, Minput_delete_surrounding_text, ibus_m17n_engine_callback); - - g_hash_table_insert (im_table, g_strdup (engine_name), im); + engine_name = ibus_engine_get_name ((IBusEngine *) m17n); + if (!ibus_m17n_scan_engine_name (engine_name, &lang, &name)) { + g_free (lang); + g_free (name); + return NULL; } - } - - if (im == NULL) { - g_warning ("Can not find m17n keymap %s", engine_name); - g_strfreev (strv); - g_object_unref (m17n); - return NULL; - } - - m17n->context = minput_create_ic (im, NULL); - mplist_add (m17n->context->plist, msymbol ("IBusEngine"), m17n); - - m17n->config_section = g_strdup_printf ("engine/M17N/%s/%s", - lang, name); - g_strfreev (strv); - - preedit_highlight = ibus_m17n_preedit_highlight (engine_name); - if (ibus_config_get_value (config, - m17n->config_section, - "preedit_foreground", - &value)) { - const gchar *hex = g_value_get_string (&value); - guint color = ibus_m17n_parse_color (hex); - if (color != (guint)-1) - preedit_foreground = color; - g_value_unset (&value); - } else if (preedit_highlight) - preedit_foreground = PREEDIT_FOREGROUND; - if (ibus_config_get_value (config, - m17n->config_section, - "preedit_background", - &value)) { - const gchar *hex = g_value_get_string (&value); - guint color = ibus_m17n_parse_color (hex); - if (color != (guint)-1) - preedit_background = color; - g_value_unset (&value); - } else if (preedit_highlight) - preedit_background = PREEDIT_BACKGROUND; + klass->im = minput_open_im (msymbol (lang), msymbol (name), NULL); + g_free (lang); + g_free (name); - if (ibus_config_get_value (config, - m17n->config_section, - "preedit_underline", - &value)) { - preedit_underline = g_value_get_int (&value); - g_value_unset (&value); - } else - preedit_underline = IBUS_ATTR_UNDERLINE_NONE; - - if (ibus_config_get_value (config, - m17n->config_section, - "lookup_table_orientation", - &value)) { - lookup_table_orientation = g_value_get_int (&value); - g_value_unset (&value); - } else - lookup_table_orientation = IBUS_ORIENTATION_SYSTEM; + if (klass->im == NULL) { + g_warning ("Can not find m17n keymap %s", engine_name); + g_object_unref (m17n); + return NULL; + } - g_signal_connect (config, "value-changed", - G_CALLBACK(ibus_config_value_changed), m17n); + mplist_put (klass->im->driver.callback_list, Minput_preedit_start, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_preedit_draw, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_preedit_done, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_status_start, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_status_draw, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_status_done, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_candidates_start, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_candidates_draw, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_candidates_done, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_set_spot, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_toggle, ibus_m17n_engine_callback); + /* + Does not set reset callback, uses the default callback in m17n. + mplist_put (klass->im->driver.callback_list, Minput_reset, ibus_m17n_engine_callback); + */ + mplist_put (klass->im->driver.callback_list, Minput_get_surrounding_text, ibus_m17n_engine_callback); + mplist_put (klass->im->driver.callback_list, Minput_delete_surrounding_text, ibus_m17n_engine_callback); + } + + m17n->context = minput_create_ic (klass->im, m17n); return (GObject *) m17n; } - static void ibus_m17n_engine_destroy (IBusM17NEngine *m17n) { @@ -379,11 +534,6 @@ ibus_m17n_engine_destroy (IBusM17NEngine *m17n) m17n->context = NULL; } - if (m17n->config_section) { - g_free (m17n->config_section); - m17n->config_section = NULL; - } - IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)m17n); } @@ -392,18 +542,19 @@ ibus_m17n_engine_update_preedit (IBusM17NEngine *m17n) { IBusText *text; gchar *buf; + IBusM17NEngineClass *klass = (IBusM17NEngineClass *) G_OBJECT_GET_CLASS (m17n); buf = ibus_m17n_mtext_to_utf8 (m17n->context->preedit); if (buf) { text = ibus_text_new_from_static_string (buf); - if (preedit_foreground != INVALID_COLOR) + if (klass->preedit_foreground != INVALID_COLOR) ibus_text_append_attribute (text, IBUS_ATTR_TYPE_FOREGROUND, - preedit_foreground, 0, -1); - if (preedit_background != INVALID_COLOR) + klass->preedit_foreground, 0, -1); + if (klass->preedit_background != INVALID_COLOR) ibus_text_append_attribute (text, IBUS_ATTR_TYPE_BACKGROUND, - preedit_background, 0, -1); + klass->preedit_background, 0, -1); ibus_text_append_attribute (text, IBUS_ATTR_TYPE_UNDERLINE, - preedit_underline, 0, -1); + klass->preedit_underline, 0, -1); ibus_engine_update_preedit_text ((IBusEngine *) m17n, text, m17n->context->cursor_pos, @@ -421,9 +572,9 @@ ibus_m17n_engine_commit_string (IBusM17NEngine *m17n, ibus_m17n_engine_update_preedit (m17n); } -/* Note on AltGr handling: While currently we expect AltGr == mod5, it - would be better to not expect the modifier always be assigned - to particular modX. However, it needs some code like: +/* Note on AltGr (Level3 Shift) handling: While currently we expect + AltGr == mod5, it would be better to not expect the modifier always + be assigned to particular modX. However, it needs some code like: KeyCode altgr = XKeysymToKeycode (display, XK_ISO_Level3_Shift); XModifierKeymap *mods = XGetModifierMapping (display); @@ -445,20 +596,26 @@ ibus_m17n_key_event_to_symbol (guint keycode, MSymbol mkeysym = Mnil; guint mask = 0; IBusKeymap *keymap; - guint base_keyval; if (keyval >= IBUS_Shift_L && keyval <= IBUS_Hyper_R) { return Mnil; } - keymap = ibus_keymap_get ("us"); - base_keyval = ibus_keymap_lookup_keysym (keymap, keycode, 0); - g_object_unref (keymap); + /* Here, keyval is already translated by IBUS_MOD5_MASK. Obtain + the untranslated keyval from the underlying keymap and + represent the translated keyval as the form "G-", which m17n-lib accepts. */ + if (modifiers & IBUS_MOD5_MASK) { + keymap = ibus_keymap_get ("us"); + keyval = ibus_keymap_lookup_keysym (keymap, keycode, + modifiers & ~IBUS_MOD5_MASK); + g_object_unref (keymap); + } keysym = g_string_new (""); - if (base_keyval >= IBUS_space && base_keyval <= IBUS_asciitilde) { - gint c = (modifiers & IBUS_MOD5_MASK) ? base_keyval : keyval; + if (keyval >= IBUS_space && keyval <= IBUS_asciitilde) { + gint c = keyval; if (keyval == IBUS_space && modifiers & IBUS_SHIFT_MASK) mask |= IBUS_SHIFT_MASK; @@ -572,7 +729,7 @@ ibus_m17n_engine_focus_in (IBusEngine *engine) IBusM17NEngine *m17n = (IBusM17NEngine *) engine; ibus_engine_register_properties (engine, m17n->prop_list); - ibus_m17n_engine_process_key (m17n, msymbol ("input-focus-in")); + ibus_m17n_engine_process_key (m17n, Minput_focus_in); parent_class->focus_in (engine); } @@ -582,7 +739,7 @@ ibus_m17n_engine_focus_out (IBusEngine *engine) { IBusM17NEngine *m17n = (IBusM17NEngine *) engine; - ibus_m17n_engine_process_key (m17n, msymbol ("input-focus-out")); + ibus_m17n_engine_process_key (m17n, Minput_focus_out); parent_class->focus_out (engine); } @@ -593,7 +750,8 @@ ibus_m17n_engine_reset (IBusEngine *engine) IBusM17NEngine *m17n = (IBusM17NEngine *) engine; parent_class->reset (engine); - ibus_m17n_engine_focus_in (engine); + + minput_reset_ic (m17n->context); } static void @@ -676,7 +834,7 @@ ibus_m17n_engine_property_activate (IBusEngine *engine, static void ibus_m17n_engine_update_lookup_table (IBusM17NEngine *m17n) { - ibus_lookup_table_clear (m17n->table); + ibus_lookup_table_clear (m17n->table); if (m17n->context->candidate_list && m17n->context->candidate_show) { IBusText *text; @@ -684,6 +842,7 @@ ibus_m17n_engine_update_lookup_table (IBusM17NEngine *m17n) group = m17n->context->candidate_list; gint i = 0; gint page = 1; + IBusM17NEngineClass *klass = (IBusM17NEngineClass *) G_OBJECT_GET_CLASS (m17n); while (1) { gint len; @@ -734,7 +893,7 @@ ibus_m17n_engine_update_lookup_table (IBusM17NEngine *m17n) } ibus_lookup_table_set_cursor_pos (m17n->table, m17n->context->candidate_index - i); - ibus_lookup_table_set_orientation (m17n->table, lookup_table_orientation); + ibus_lookup_table_set_orientation (m17n->table, klass->lookup_table_orientation); text = ibus_text_new_from_printf ("( %d / %d )", page, mplist_length (m17n->context->candidate_list)); @@ -752,15 +911,14 @@ ibus_m17n_engine_callback (MInputContext *context, MSymbol command) { IBusM17NEngine *m17n = NULL; - MPlist *p = NULL; - p = mplist_find_by_key (context->plist, msymbol ("IBusEngine")); - if (p) { - m17n = (IBusM17NEngine *) mplist_value (p); - } + m17n = context->arg; + g_return_if_fail (m17n != NULL); - if (m17n == NULL) { - return; + /* the callback may be called in minput_create_ic, in the time + * m17n->context has not be assigned, so need assign it. */ + if (m17n->context == NULL) { + m17n->context = context; } if (command == Minput_preedit_start) { diff --git a/src/engine.h b/src/engine.h index 7c0b4d9..bdd6492 100644 --- a/src/engine.h +++ b/src/engine.h @@ -4,9 +4,6 @@ #include -#define IBUS_TYPE_M17N_ENGINE \ - (ibus_m17n_engine_get_type ()) - -GType ibus_m17n_engine_get_type (void); +GType ibus_m17n_engine_get_type_for_name (const gchar *name); #endif diff --git a/src/m17n.xml.in.in b/src/m17n.xml.in.in index 3ea4394..97d72d2 100644 --- a/src/m17n.xml.in.in +++ b/src/m17n.xml.in.in @@ -11,6 +11,7 @@ ibus-m17n /usr/share/m17n/ + ${setupdir}/default.xml diff --git a/src/m17nutil.c b/src/m17nutil.c index ae0fe56..6d6961f 100644 --- a/src/m17nutil.c +++ b/src/m17nutil.c @@ -7,39 +7,17 @@ static MConverter *utf8_converter = NULL; -static const gchar *keymap[] = { - "m17n:as:phonetic", - "m17n:bn:inscript", - "m17n:gu:inscript", - "m17n:hi:inscript", - "m17n:kn:kgp", - "m17n:ks:kbd", - "m17n:mai:inscript", - "m17n:ml:inscript", - "m17n:mr:inscript", - "m17n:ne:rom", - "m17n:or:inscript", - "m17n:pa:inscript", - "m17n:sa:harvard-kyoto", - "m17n:sd:inscript", - "m17n:si:wijesekera", - "m17n:ta:tamil99", - "m17n:te:inscript" -}; +#define DEFAULT_XML (SETUPDIR "/default.xml") -static const gchar *preedit_highlight[] = { - "m17n:ja:anthy", - "m17n:zh:cangjie", - "m17n:zh:py-b5", - "m17n:zh:py-gb", - "m17n:zh:py", - "m17n:zh:quick", - "m17n:zh:tonepy-b5", - "m17n:zh:tonepy-gb", - "m17n:zh:tonepy", - "m17n:zh:util", +struct _IBusM17NEngineConfigNode { + gchar *name; + IBusM17NEngineConfig config; }; +typedef struct _IBusM17NEngineConfigNode IBusM17NEngineConfigNode; + +static GSList *config_list = NULL; + void ibus_m17n_init_common (void) { @@ -101,11 +79,16 @@ guint ibus_m17n_parse_color (const gchar *hex) { guint color; - if (hex && *hex == '#' && - ((color = strtoul (&hex[1], NULL, 16)) != ULONG_MAX || - errno != ERANGE)) - return color; - return (guint)-1; + + if (!hex || *hex != '#') + return (guint)-1; + + errno = 0; + color = strtoul (&hex[1], NULL, 16); + if ((errno == ERANGE && color == ULONG_MAX) + || (errno != 0 && color == 0)) + return (guint)-1; + return color; } static IBusEngineDesc * @@ -113,7 +96,8 @@ ibus_m17n_engine_new (MSymbol lang, MSymbol name, MText *title, MText *icon, - MText *desc) + MText *desc, + IBusM17NEngineConfig *config) { IBusEngineDesc *engine; gchar *engine_name; @@ -121,7 +105,6 @@ ibus_m17n_engine_new (MSymbol lang, gchar *engine_title; gchar *engine_icon; gchar *engine_desc; - gint i; engine_name = g_strdup_printf ("m17n:%s:%s", msymbol_name (lang), msymbol_name (name)); @@ -138,16 +121,7 @@ ibus_m17n_engine_new (MSymbol lang, "", engine_icon ? engine_icon : "", "us"); - /* set default rank to 0 */ - engine->rank = 0; - - for (i = 0; i < G_N_ELEMENTS(keymap); i++) { - if (strcmp (engine_name, keymap[i]) == 0) { - /* set rank of default keymap to 1 */ - engine->rank = 1; - break; - } - } + engine->rank = config->rank; g_free (engine_name); g_free (engine_longname); @@ -178,10 +152,28 @@ ibus_m17n_list_engines (void) MText *icon = NULL; MText *desc = NULL; MPlist *l; + gchar *engine_name; + IBusM17NEngineConfig *config; lang = tag[1]; name = tag[2]; + /* ignore input-method explicitly blacklisted in default.xml */ + engine_name = g_strdup_printf ("m17n:%s:%s", msymbol_name (lang), msymbol_name (name)); + config = ibus_m17n_get_engine_config (engine_name); + if (config == NULL) { + g_warning ("can't load config for %s", engine_name); + g_free (engine_name); + continue; + } + if (config->rank < 0) { + g_warning ("skipped %s since its rank is lower than 0", + engine_name); + g_free (engine_name); + continue; + } + g_free (engine_name); + l = minput_get_variable (lang, name, msymbol ("candidates-charset")); if (l) { /* check candidates encoding */ @@ -226,7 +218,7 @@ ibus_m17n_list_engines (void) icon = mplist_value (n); } - engines = g_list_append (engines, ibus_m17n_engine_new (lang, name, title, icon, desc)); + engines = g_list_append (engines, ibus_m17n_engine_new (lang, name, title, icon, desc, config)); if (desc) m17n_object_unref (desc); @@ -241,11 +233,58 @@ ibus_m17n_list_engines (void) return engines; } +IBusM17NEngineConfig * +ibus_m17n_get_engine_config (const gchar *engine_name) +{ + GSList *p; + + for (p = config_list; p != NULL; p = p->next) { + IBusM17NEngineConfigNode *cnode = p->data; + + if (g_pattern_match_simple (cnode->name, engine_name)) + return &cnode->config; + } + g_return_val_if_reached (NULL); +} + +static gboolean +ibus_m17n_engine_config_parse_xml_node (IBusM17NEngineConfigNode *cnode, + XMLNode *node) +{ + GList *p; + + for (p = node->sub_nodes; p != NULL; p = p->next) { + XMLNode *sub_node = (XMLNode *) p->data; + + if (g_strcmp0 (sub_node->name, "name") == 0) { + g_free (cnode->name); + cnode->name = g_strdup (sub_node->text); + continue; + } + if (g_strcmp0 (sub_node->name , "rank") == 0) { + cnode->config.rank = atoi (sub_node->text); + continue; + } + if (g_strcmp0 (sub_node->name , "preedit-highlight") == 0) { + if (g_ascii_strcasecmp ("TRUE", sub_node->text) == 0) + cnode->config.preedit_highlight = TRUE; + else if (g_ascii_strcasecmp ("FALSE", sub_node->text) != 0) + g_warning ("<%s> element contains invalid boolean value %s", + sub_node->name, sub_node->text); + continue; + } + g_warning (" element contains invalid element <%s>", + sub_node->name); + } + return TRUE; +} + IBusComponent * ibus_m17n_get_component (void) { GList *engines, *p; IBusComponent *component; + XMLNode *node; component = ibus_component_new ("org.freedesktop.IBus.M17n", N_("M17N"), @@ -256,26 +295,39 @@ ibus_m17n_get_component (void) "", "ibus-m17n"); + node = ibus_xml_parse_file (DEFAULT_XML); + if (node && g_strcmp0 (node->name, "engines") == 0) { + for (p = node->sub_nodes; p != NULL; p = p->next) { + XMLNode *sub_node = p->data; + IBusM17NEngineConfigNode *cnode; + + if (g_strcmp0 (sub_node->name, "engine") != 0) { + g_warning (" element contains invalid element <%s>", + sub_node->name); + continue; + } + + cnode = g_slice_new0 (IBusM17NEngineConfigNode); + if (!ibus_m17n_engine_config_parse_xml_node (cnode, sub_node)) { + g_slice_free (IBusM17NEngineConfigNode, cnode); + continue; + } + config_list = g_slist_prepend (config_list, cnode); + } + config_list = g_slist_reverse (config_list); + } else + g_warning ("failed to parse %s", DEFAULT_XML); + if (node) + ibus_xml_free (node); + engines = ibus_m17n_list_engines (); - for (p = engines; p != NULL; p = p->next) { - ibus_component_add_engine (component, (IBusEngineDesc *) p->data); - } + for (p = engines; p != NULL; p = p->next) + ibus_component_add_engine (component, p->data); g_list_free (engines); - return component; -} -gboolean -ibus_m17n_preedit_highlight (const gchar *engine_name) -{ - gint i; - - for (i = 0; i < G_N_ELEMENTS(preedit_highlight); i++) { - if (strcmp (engine_name, preedit_highlight[i]) == 0) - return TRUE; - } - return FALSE; + return component; } #ifdef DEBUG @@ -304,4 +356,3 @@ int main () return 0; } #endif - diff --git a/src/m17nutil.h b/src/m17nutil.h index 7561505..a9be667 100644 --- a/src/m17nutil.h +++ b/src/m17nutil.h @@ -10,6 +10,16 @@ #define PREEDIT_FOREGROUND 0x00000000 #define PREEDIT_BACKGROUND 0x00c8c8f0 +struct _IBusM17NEngineConfig { + /* engine rank */ + gint rank; + + /* whether to highlight preedit */ + gboolean preedit_highlight; +}; + +typedef struct _IBusM17NEngineConfig IBusM17NEngineConfig; + void ibus_m17n_init_common (void); void ibus_m17n_init (IBusBus *bus); GList *ibus_m17n_list_engines (void); @@ -18,5 +28,6 @@ gchar *ibus_m17n_mtext_to_utf8 (MText *text); gunichar *ibus_m17n_mtext_to_ucs4 (MText *text, glong *nchars); guint ibus_m17n_parse_color (const gchar *hex); -gboolean ibus_m17n_preedit_highlight (const gchar *engine_name); +IBusM17NEngineConfig + *ibus_m17n_get_engine_config (const gchar *engine_name); #endif diff --git a/src/main.c b/src/main.c index b8d7c72..e76898d 100644 --- a/src/main.c +++ b/src/main.c @@ -51,7 +51,13 @@ start_component (void) engines = ibus_component_get_engines (component); for (p = engines; p != NULL; p = p->next) { IBusEngineDesc *engine = (IBusEngineDesc *)p->data; - ibus_factory_add_engine (factory, engine->name, IBUS_TYPE_M17N_ENGINE); + GType type = ibus_m17n_engine_get_type_for_name (engine->name); + + if (type == G_TYPE_INVALID) { + g_debug ("Can not create engine type for %s", engine->name); + continue; + } + ibus_factory_add_engine (factory, engine->name, type); } if (ibus) { @@ -74,8 +80,7 @@ print_engines_xml (void) ibus_init (); - bus = ibus_bus_new (); - ibus_m17n_init (bus); + ibus_m17n_init_common (); component = ibus_m17n_get_component (); output = g_string_new (""); diff --git a/src/setup.c b/src/setup.c index 7442159..0fe6e1b 100644 --- a/src/setup.c +++ b/src/setup.c @@ -83,6 +83,7 @@ parse_value (MPlist *plist, gchar *text) if (mplist_key (plist) == Minteger) { long val; + errno = 0; val = strtol (text, NULL, 10); if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0))