diff --git a/src/engine.c b/src/engine.c index 85c4074..a72a38f 100644 --- a/src/engine.c +++ b/src/engine.c @@ -1416,18 +1416,10 @@ ibus_hangul_engine_property_activate (IBusEngine *engine, if (strcmp(prop_name, "setup") == 0) { GError *error = NULL; gchar *argv[2] = { NULL, }; - gchar *path; - const char* libexecdir; - libexecdir = g_getenv("LIBEXECDIR"); - if (libexecdir == NULL) - libexecdir = LIBEXECDIR; - - path = g_build_filename(libexecdir, "ibus-setup-hangul", NULL); - argv[0] = path; + argv[0] = "ibus-setup-hangul"; argv[1] = NULL; - g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &error); - g_free(path); + g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error); } else if (strcmp(prop_name, "InputMode") == 0) { IBusHangulEngine *hangul = (IBusHangulEngine *) engine; diff --git a/src/engine.c.setup-abspath b/src/engine.c.setup-abspath deleted file mode 100644 index a72a38f..0000000 --- a/src/engine.c.setup-abspath +++ /dev/null @@ -1,1762 +0,0 @@ -/* vim:set et sts=4: */ -/* ibus-hangul - The Hangul Engine For IBus - * Copyright (C) 2008-2009 Peng Huang - * Copyright (C) 2009-2011 Choe Hwanjin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "i18n.h" -#include "engine.h" -#include "ustring.h" - - -typedef struct _IBusHangulEngine IBusHangulEngine; -typedef struct _IBusHangulEngineClass IBusHangulEngineClass; - -typedef struct _HotkeyList HotkeyList; - -enum { - INPUT_MODE_HANGUL, - INPUT_MODE_LATIN, - INPUT_MODE_COUNT, -}; - -struct _IBusHangulEngine { - IBusEngineSimple parent; - - /* members */ - HangulInputContext *context; - UString* preedit; - int input_mode; - unsigned int input_purpose; - gboolean hanja_mode; - HanjaList* hanja_list; - int last_lookup_method; - - IBusLookupTable *table; - - IBusProperty *prop_hangul_mode; - IBusProperty *prop_hanja_mode; - IBusPropList *prop_list; - - IBusText *input_mode_symbols[INPUT_MODE_COUNT]; -}; - -struct _IBusHangulEngineClass { - IBusEngineSimpleClass parent; -}; - -struct KeyEvent { - guint keyval; - guint modifiers; -}; - -struct _HotkeyList { - guint all_modifiers; - GArray *keys; -}; - -enum { - LOOKUP_METHOD_EXACT, - LOOKUP_METHOD_PREFIX, - LOOKUP_METHOD_SUFFIX, -}; - -/* functions prototype */ -static void ibus_hangul_engine_class_init - (IBusHangulEngineClass *klass); -static void ibus_hangul_engine_init (IBusHangulEngine *hangul); -static GObject* - ibus_hangul_engine_constructor - (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params); -static void ibus_hangul_engine_destroy (IBusHangulEngine *hangul); -static gboolean - ibus_hangul_engine_process_key_event - (IBusEngine *engine, - guint keyval, - guint keycode, - guint modifiers); -static void ibus_hangul_engine_focus_in (IBusEngine *engine); -static void ibus_hangul_engine_focus_out (IBusEngine *engine); -static void ibus_hangul_engine_reset (IBusEngine *engine); -static void ibus_hangul_engine_enable (IBusEngine *engine); -static void ibus_hangul_engine_disable (IBusEngine *engine); -#if 0 -static void ibus_engine_set_cursor_location (IBusEngine *engine, - gint x, - gint y, - gint w, - gint h); -static void ibus_hangul_engine_set_capabilities - (IBusEngine *engine, - guint caps); -#endif -static void ibus_hangul_engine_page_up (IBusEngine *engine); -static void ibus_hangul_engine_page_down (IBusEngine *engine); -static void ibus_hangul_engine_cursor_up (IBusEngine *engine); -static void ibus_hangul_engine_cursor_down (IBusEngine *engine); -static void ibus_hangul_engine_property_activate - (IBusEngine *engine, - const gchar *prop_name, - guint prop_state); -#if 0 -static void ibus_hangul_engine_property_show - (IBusEngine *engine, - const gchar *prop_name); -static void ibus_hangul_engine_property_hide - (IBusEngine *engine, - const gchar *prop_name); -#endif - -static void ibus_hangul_engine_candidate_clicked - (IBusEngine *engine, - guint index, - guint button, - guint state); -static void ibus_hangul_engine_set_content_type - (IBusEngine *engine, - guint purpose, - guint hints); - -static void ibus_hangul_engine_flush (IBusHangulEngine *hangul); -static void ibus_hangul_engine_clear_preedit_text - (IBusHangulEngine *hangul); -static void ibus_hangul_engine_update_preedit_text - (IBusHangulEngine *hangul); - -static void ibus_hangul_engine_update_lookup_table - (IBusHangulEngine *hangul); -static gboolean ibus_hangul_engine_has_preedit - (IBusHangulEngine *hangul); -static void ibus_hangul_engine_switch_input_mode - (IBusHangulEngine *hangul); -static void ibus_hangul_engine_set_input_mode - (IBusHangulEngine *hangul, - int input_mode); -static IBusText* - ibus_hangul_engine_get_input_mode_symbol - (IBusHangulEngine *hangul, - int input_mode); - -static bool ibus_hangul_engine_on_transition - (HangulInputContext *hic, - ucschar c, - const ucschar *preedit, - void *data); - -static void settings_changed (GSettings *settings, - const gchar *key, - gpointer user_data); - -static void lookup_table_set_visible (IBusLookupTable *table, - gboolean flag); -static gboolean lookup_table_is_visible - (IBusLookupTable *table); - -static gboolean key_event_list_match (GArray *list, - guint keyval, - guint modifiers); - -static void hotkey_list_init (HotkeyList *list); -static void hotkey_list_fini (HotkeyList *list); -static void hotkey_list_set_from_string (HotkeyList *list, - const char *str); -static void hotkey_list_append (HotkeyList *list, - guint keyval, - guint modifiers); -static gboolean hotkey_list_match (HotkeyList *list, - guint keyval, - guint modifiers); -static gboolean hotkey_list_has_modifier (HotkeyList *list, - guint keyval); - -static glong ucschar_strlen (const ucschar* str); - -static IBusEngineSimpleClass *parent_class = NULL; -static HanjaTable *hanja_table = NULL; -static HanjaTable *symbol_table = NULL; -static GSettings *settings_hangul = NULL; -static GSettings *settings_panel = NULL; -static GString *hangul_keyboard = NULL; -static HotkeyList hanja_keys; -static HotkeyList switch_keys; -static HotkeyList on_keys; -static HotkeyList off_keys; -static int lookup_table_orientation = 0; -static IBusKeymap *keymap = NULL; -static gboolean word_commit = FALSE; -static gboolean auto_reorder = TRUE; -static gboolean disable_latin_mode = FALSE; -static int initial_input_mode = INPUT_MODE_LATIN; -/** - * whether to use event forwarding workaround - */ -static gboolean use_event_forwarding = TRUE; - -static glong -ucschar_strlen (const ucschar* str) -{ - const ucschar* p = str; - while (*p != 0) - p++; - return p - str; -} - -GType -ibus_hangul_engine_get_type (void) -{ - static GType type = 0; - - static const GTypeInfo type_info = { - sizeof (IBusHangulEngineClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) ibus_hangul_engine_class_init, - NULL, - NULL, - sizeof (IBusHangulEngine), - 0, - (GInstanceInitFunc) ibus_hangul_engine_init, - }; - - if (type == 0) { - type = g_type_register_static (IBUS_TYPE_ENGINE_SIMPLE, - "IBusHangulEngine", - &type_info, - (GTypeFlags) 0); - } - - return type; -} - -void -ibus_hangul_init (IBusBus *bus) -{ - GVariant* value = NULL; - - hanja_table = hanja_table_load (NULL); - - symbol_table = hanja_table_load (IBUSHANGUL_DATADIR "/data/symbol.txt"); - - settings_hangul = g_settings_new ("org.freedesktop.ibus.engine.hangul"); - settings_panel = g_settings_new ("org.freedesktop.ibus.panel"); - - hangul_keyboard = g_string_new_len (NULL, 8); - value = g_settings_get_value (settings_hangul, "hangul-keyboard"); - if (value != NULL) { - const gchar* str = g_variant_get_string (value, NULL); - g_string_assign (hangul_keyboard, str); - g_clear_pointer (&value, g_variant_unref); - } - - hotkey_list_init(&switch_keys); - - value = g_settings_get_value (settings_hangul, "switch-keys"); - if (value != NULL) { - const gchar* str = g_variant_get_string (value, NULL); - hotkey_list_set_from_string(&switch_keys, str); - g_clear_pointer (&value, g_variant_unref); - } else { - hotkey_list_append(&switch_keys, IBUS_Hangul, 0); - hotkey_list_append(&switch_keys, IBUS_space, IBUS_SHIFT_MASK); - } - - hotkey_list_init(&hanja_keys); - - value = g_settings_get_value (settings_hangul, "hanja-keys"); - if (value != NULL) { - const gchar* str = g_variant_get_string (value, NULL); - hotkey_list_set_from_string(&hanja_keys, str); - g_clear_pointer (&value, g_variant_unref); - } else { - hotkey_list_append(&hanja_keys, IBUS_Hangul_Hanja, 0); - hotkey_list_append(&hanja_keys, IBUS_F9, 0); - } - - hotkey_list_init (&on_keys); - value = g_settings_get_value (settings_hangul, "on-keys"); - if (value != NULL) { - const gchar* str = g_variant_get_string (value, NULL); - hotkey_list_set_from_string (&on_keys, str); - g_clear_pointer (&value, g_variant_unref); - } - - hotkey_list_init (&off_keys); - value = g_settings_get_value (settings_hangul, "off-keys"); - if (value != NULL) { - const gchar* str = g_variant_get_string (value, NULL); - hotkey_list_set_from_string (&off_keys, str); - g_clear_pointer (&value, g_variant_unref); - } - - value = g_settings_get_value (settings_hangul, "word-commit"); - if (value != NULL) { - word_commit = g_variant_get_boolean (value); - g_clear_pointer (&value, g_variant_unref); - } - - value = g_settings_get_value (settings_hangul, "auto-reorder"); - if (value != NULL) { - auto_reorder = g_variant_get_boolean (value); - g_clear_pointer (&value, g_variant_unref); - } - - value = g_settings_get_value (settings_hangul, "disable-latin-mode"); - if (value != NULL) { - disable_latin_mode = g_variant_get_boolean (value); - g_clear_pointer (&value, g_variant_unref); - } - - value = g_settings_get_value (settings_hangul, "initial-input-mode"); - if (value != NULL) { - const gchar* str = g_variant_get_string (value, NULL); - if (strcmp(str, "latin") == 0) { - initial_input_mode = INPUT_MODE_LATIN; - } else if (strcmp(str, "hangul") == 0) { - initial_input_mode = INPUT_MODE_HANGUL; - } - g_clear_pointer (&value, g_variant_unref); - } - - value = g_settings_get_value (settings_hangul, "use-event-forwarding"); - if (value != NULL) { - use_event_forwarding = g_variant_get_boolean (value); - g_clear_pointer (&value, g_variant_unref); - } - - value = g_settings_get_value (settings_panel, "lookup-table-orientation"); - if (value != NULL) { - lookup_table_orientation = g_variant_get_int32(value); - g_clear_pointer (&value, g_variant_unref); - } - - keymap = ibus_keymap_get("us"); -} - -void -ibus_hangul_exit (void) -{ - if (keymap != NULL) { - g_object_unref(keymap); - keymap = NULL; - } - - hotkey_list_fini (&switch_keys); - hotkey_list_fini (&hanja_keys); - hotkey_list_fini (&on_keys); - hotkey_list_fini (&off_keys); - - hanja_table_delete (hanja_table); - hanja_table = NULL; - - hanja_table_delete (symbol_table); - symbol_table = NULL; - - g_clear_object (&settings_hangul); - g_clear_object (&settings_panel); - - g_string_free (hangul_keyboard, TRUE); - hangul_keyboard = NULL; -} - -static void -ibus_hangul_engine_class_init (IBusHangulEngineClass *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 = (IBusEngineSimpleClass *) g_type_class_peek_parent (klass); - - object_class->constructor = ibus_hangul_engine_constructor; - ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_hangul_engine_destroy; - - engine_class->process_key_event = ibus_hangul_engine_process_key_event; - - engine_class->reset = ibus_hangul_engine_reset; - engine_class->enable = ibus_hangul_engine_enable; - engine_class->disable = ibus_hangul_engine_disable; - - engine_class->focus_in = ibus_hangul_engine_focus_in; - engine_class->focus_out = ibus_hangul_engine_focus_out; - - engine_class->page_up = ibus_hangul_engine_page_up; - engine_class->page_down = ibus_hangul_engine_page_down; - - engine_class->cursor_up = ibus_hangul_engine_cursor_up; - engine_class->cursor_down = ibus_hangul_engine_cursor_down; - - engine_class->property_activate = ibus_hangul_engine_property_activate; - - engine_class->candidate_clicked = ibus_hangul_engine_candidate_clicked; - engine_class->set_content_type = ibus_hangul_engine_set_content_type; -} - -static void -ibus_hangul_engine_init (IBusHangulEngine *hangul) -{ - IBusProperty* prop; - IBusText* label; - IBusText* tooltip; - IBusText* symbol; - - hangul->context = hangul_ic_new (hangul_keyboard->str); - hangul_ic_connect_callback (hangul->context, "transition", - ibus_hangul_engine_on_transition, hangul); - - hangul->preedit = ustring_new(); - hangul->hanja_list = NULL; - hangul->input_mode = initial_input_mode; - hangul->input_purpose = IBUS_INPUT_PURPOSE_FREE_FORM; - hangul->hanja_mode = FALSE; - hangul->last_lookup_method = LOOKUP_METHOD_PREFIX; - - if (disable_latin_mode) { - hangul->input_mode = INPUT_MODE_HANGUL; - } - - hangul->prop_list = ibus_prop_list_new (); - g_object_ref_sink (hangul->prop_list); - - label = ibus_text_new_from_string (_("Hangul mode")); - tooltip = ibus_text_new_from_string (_("Enable/Disable Hangul mode")); - prop = ibus_property_new ("InputMode", - PROP_TYPE_TOGGLE, - label, - NULL, - tooltip, - TRUE, TRUE, PROP_STATE_UNCHECKED, NULL); - symbol = ibus_hangul_engine_get_input_mode_symbol (hangul, - hangul->input_mode); - ibus_property_set_symbol(prop, symbol); - g_object_ref_sink (prop); - ibus_prop_list_append (hangul->prop_list, prop); - hangul->prop_hangul_mode = prop; - - label = ibus_text_new_from_string (_("Hanja lock")); - tooltip = ibus_text_new_from_string (_("Enable/Disable Hanja mode")); - prop = ibus_property_new ("hanja_mode", - PROP_TYPE_TOGGLE, - label, - NULL, - tooltip, - TRUE, TRUE, PROP_STATE_UNCHECKED, NULL); - g_object_ref_sink (prop); - ibus_prop_list_append (hangul->prop_list, prop); - hangul->prop_hanja_mode = prop; - - label = ibus_text_new_from_string (_("Setup")); - tooltip = ibus_text_new_from_string (_("Configure hangul engine")); - prop = ibus_property_new ("setup", - PROP_TYPE_NORMAL, - label, - "gtk-preferences", - tooltip, - TRUE, TRUE, PROP_STATE_UNCHECKED, NULL); - ibus_prop_list_append (hangul->prop_list, prop); - - hangul->table = ibus_lookup_table_new (9, 0, TRUE, FALSE); - g_object_ref_sink (hangul->table); - - g_signal_connect (settings_hangul, "changed", - G_CALLBACK (settings_changed), hangul); - g_signal_connect (settings_panel, "changed", - G_CALLBACK (settings_changed), hangul); -} - -static GObject* -ibus_hangul_engine_constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - IBusHangulEngine *hangul; - - hangul = (IBusHangulEngine *) G_OBJECT_CLASS (parent_class)->constructor (type, - n_construct_params, - construct_params); - - return (GObject *)hangul; -} - - -static void -ibus_hangul_engine_destroy (IBusHangulEngine *hangul) -{ - int i; - IBusText **symbols; - - if (hangul->prop_hangul_mode) { - g_object_unref (hangul->prop_hangul_mode); - hangul->prop_hangul_mode = NULL; - } - - if (hangul->prop_hanja_mode) { - g_object_unref (hangul->prop_hanja_mode); - hangul->prop_hanja_mode = NULL; - } - - if (hangul->prop_list) { - g_object_unref (hangul->prop_list); - hangul->prop_list = NULL; - } - - if (hangul->table) { - g_object_unref (hangul->table); - hangul->table = NULL; - } - - if (hangul->context) { - hangul_ic_delete (hangul->context); - hangul->context = NULL; - } - - symbols = hangul->input_mode_symbols; - for (i = 0; i < INPUT_MODE_COUNT; ++i) { - if (symbols[i] != NULL) { - g_object_unref(symbols[i]); - symbols[i] = NULL; - } - } - - IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)hangul); -} - -static void -ibus_hangul_engine_clear_preedit_text (IBusHangulEngine *hangul) -{ - IBusText *text; - - text = ibus_text_new_from_static_string (""); - ibus_engine_update_preedit_text ((IBusEngine *)hangul, text, 0, FALSE); -} - -static void -ibus_hangul_engine_update_preedit_text (IBusHangulEngine *hangul) -{ - const ucschar *hic_preedit; - IBusText *text; - UString *preedit; - gint preedit_len; - - // ibus-hangul's preedit string is made up of ibus context's - // internal preedit string and libhangul's preedit string. - // libhangul only supports one syllable preedit string. - // In order to make longer preedit string, ibus-hangul maintains - // internal preedit string. - hic_preedit = hangul_ic_get_preedit_string (hangul->context); - - preedit = ustring_dup (hangul->preedit); - preedit_len = ustring_length(preedit); - ustring_append_ucs4 (preedit, hic_preedit, -1); - - if (ustring_length(preedit) > 0) { - IBusPreeditFocusMode preedit_option = IBUS_ENGINE_PREEDIT_COMMIT; - - if (hangul->hanja_list != NULL) - preedit_option = IBUS_ENGINE_PREEDIT_CLEAR; - - text = ibus_text_new_from_ucs4 ((gunichar*)preedit->data); - // ibus-hangul's internal preedit string - ibus_text_append_attribute (text, IBUS_ATTR_TYPE_UNDERLINE, - IBUS_ATTR_UNDERLINE_SINGLE, 0, preedit_len); - // Preedit string from libhangul context. - // This is currently composing syllable. - ibus_text_append_attribute (text, IBUS_ATTR_TYPE_FOREGROUND, - 0x00ffffff, preedit_len, -1); - ibus_text_append_attribute (text, IBUS_ATTR_TYPE_BACKGROUND, - 0x00000000, preedit_len, -1); - ibus_engine_update_preedit_text_with_mode ((IBusEngine *)hangul, - text, - ibus_text_get_length (text), - TRUE, - preedit_option); - } else { - text = ibus_text_new_from_static_string (""); - ibus_engine_update_preedit_text ((IBusEngine *)hangul, text, 0, FALSE); - } - - ustring_delete(preedit); -} - -static void -ibus_hangul_engine_update_lookup_table_ui (IBusHangulEngine *hangul) -{ - guint cursor_pos; - const char* comment; - IBusText* text; - - // update aux text - cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table); - comment = hanja_list_get_nth_comment (hangul->hanja_list, cursor_pos); - - text = ibus_text_new_from_string (comment); - ibus_engine_update_auxiliary_text ((IBusEngine *)hangul, text, TRUE); - - // update lookup table - ibus_engine_update_lookup_table ((IBusEngine *)hangul, hangul->table, TRUE); -} - -static void -ibus_hangul_engine_commit_current_candidate (IBusHangulEngine *hangul) -{ - guint cursor_pos; - const char* key; - const char* value; - const ucschar* hic_preedit; - glong key_len; - glong hic_preedit_len; - glong preedit_len; - - IBusText* text; - - cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table); - key = hanja_list_get_nth_key (hangul->hanja_list, cursor_pos); - value = hanja_list_get_nth_value (hangul->hanja_list, cursor_pos); - hic_preedit = hangul_ic_get_preedit_string (hangul->context); - - key_len = g_utf8_strlen(key, -1); - preedit_len = ustring_length(hangul->preedit); - hic_preedit_len = ucschar_strlen (hic_preedit); - - if (hangul->last_lookup_method == LOOKUP_METHOD_PREFIX) { - if (preedit_len == 0 && hic_preedit_len == 0) { - /* remove surrounding_text */ - if (key_len > 0) { - ibus_engine_delete_surrounding_text ((IBusEngine *)hangul, - -key_len , key_len); - } - } else { - /* remove ibus preedit text */ - if (key_len > 0) { - glong n = MIN(key_len, preedit_len); - ustring_erase (hangul->preedit, 0, n); - key_len -= preedit_len; - } - - /* remove hic preedit text */ - if (key_len > 0) { - hangul_ic_reset (hangul->context); - key_len -= hic_preedit_len; - } - } - } else { - /* remove hic preedit text */ - if (hic_preedit_len > 0) { - hangul_ic_reset (hangul->context); - key_len -= hic_preedit_len; - } - - /* remove ibus preedit text */ - if (key_len > preedit_len) { - ustring_erase (hangul->preedit, 0, preedit_len); - key_len -= preedit_len; - } else if (key_len > 0) { - ustring_erase (hangul->preedit, 0, key_len); - key_len = 0; - } - - /* remove surrounding_text */ - if (key_len > 0) { - ibus_engine_delete_surrounding_text ((IBusEngine *)hangul, - -key_len , key_len); - } - } - - /* clear preedit text before commit */ - ibus_hangul_engine_clear_preedit_text (hangul); - - text = ibus_text_new_from_string (value); - ibus_engine_commit_text ((IBusEngine *)hangul, text); - - ibus_hangul_engine_update_preedit_text (hangul); -} - -static gchar* -h_ibus_text_get_substring (IBusText* ibus_text, glong p1, glong p2) -{ - const gchar* text; - const gchar* begin; - const gchar* end; - gchar* substring; - glong limit; - glong pos; - glong n; - - text = ibus_text_get_text (ibus_text); - limit = ibus_text_get_length (ibus_text) + 1; - if (text == NULL || limit == 0) - return NULL; - - p1 = MAX(0, p1); - p2 = MAX(0, p2); - - pos = MIN(p1, p2); - n = ABS(p2 - p1); - - if (pos + n > limit) - n = limit - pos; - - begin = g_utf8_offset_to_pointer (text, pos); - end = g_utf8_offset_to_pointer (begin, n); - - substring = g_strndup (begin, end - begin); - return substring; -} - -static HanjaList* -ibus_hangul_engine_lookup_hanja_table (const char* key, int method) -{ - HanjaList* list = NULL; - - if (key == NULL) - return NULL; - - switch (method) { - case LOOKUP_METHOD_EXACT: - if (symbol_table != NULL) - list = hanja_table_match_exact (symbol_table, key); - - if (list == NULL) - list = hanja_table_match_exact (hanja_table, key); - - break; - case LOOKUP_METHOD_PREFIX: - if (symbol_table != NULL) - list = hanja_table_match_prefix (symbol_table, key); - - if (list == NULL) - list = hanja_table_match_prefix (hanja_table, key); - - break; - case LOOKUP_METHOD_SUFFIX: - if (symbol_table != NULL) - list = hanja_table_match_suffix (symbol_table, key); - - if (list == NULL) - list = hanja_table_match_suffix (hanja_table, key); - - break; - } - - return list; -} - -static void -ibus_hangul_engine_update_hanja_list (IBusHangulEngine *hangul) -{ - gchar* hanja_key; - gchar* preedit_utf8; - const ucschar* hic_preedit; - UString* preedit; - int lookup_method; - IBusText* ibus_text = NULL; - guint cursor_pos = 0; - guint anchor_pos = 0; - - if (hangul->hanja_list != NULL) { - hanja_list_delete (hangul->hanja_list); - hangul->hanja_list = NULL; - } - - hic_preedit = hangul_ic_get_preedit_string (hangul->context); - - hanja_key = NULL; - lookup_method = LOOKUP_METHOD_PREFIX; - - preedit = ustring_dup (hangul->preedit); - ustring_append_ucs4 (preedit, hic_preedit, -1); - - if (ustring_length(preedit) > 0) { - preedit_utf8 = ustring_to_utf8 (preedit, -1); - if (word_commit || hangul->hanja_mode) { - hanja_key = preedit_utf8; - lookup_method = LOOKUP_METHOD_PREFIX; - } else { - gchar* substr; - ibus_engine_get_surrounding_text ((IBusEngine *)hangul, &ibus_text, - &cursor_pos, &anchor_pos); - - substr = h_ibus_text_get_substring (ibus_text, - cursor_pos - 64, cursor_pos); - - if (substr != NULL) { - hanja_key = g_strconcat (substr, preedit_utf8, NULL); - g_free (preedit_utf8); - } else { - hanja_key = preedit_utf8; - } - lookup_method = LOOKUP_METHOD_SUFFIX; - } - } else { - ibus_engine_get_surrounding_text ((IBusEngine *)hangul, &ibus_text, - &cursor_pos, &anchor_pos); - if (cursor_pos != anchor_pos) { - // If we have selection in surrounding text, we use that. - hanja_key = h_ibus_text_get_substring (ibus_text, - cursor_pos, anchor_pos); - lookup_method = LOOKUP_METHOD_EXACT; - } else { - hanja_key = h_ibus_text_get_substring (ibus_text, - cursor_pos - 64, cursor_pos); - lookup_method = LOOKUP_METHOD_SUFFIX; - } - } - - if (hanja_key != NULL) { - hangul->hanja_list = ibus_hangul_engine_lookup_hanja_table (hanja_key, - lookup_method); - hangul->last_lookup_method = lookup_method; - g_free (hanja_key); - } - - ustring_delete (preedit); - - if (ibus_text != NULL) - g_object_unref (ibus_text); -} - -static void -ibus_hangul_engine_apply_hanja_list (IBusHangulEngine *hangul) -{ - HanjaList* list = hangul->hanja_list; - if (list != NULL) { - int i, n; - n = hanja_list_get_size (list); - - ibus_lookup_table_clear (hangul->table); - for (i = 0; i < n; i++) { - const char* value = hanja_list_get_nth_value (list, i); - IBusText* text = ibus_text_new_from_string (value); - ibus_lookup_table_append_candidate (hangul->table, text); - } - - ibus_lookup_table_set_cursor_pos (hangul->table, 0); - ibus_hangul_engine_update_lookup_table_ui (hangul); - lookup_table_set_visible (hangul->table, TRUE); - } -} - -static void -ibus_hangul_engine_hide_lookup_table (IBusHangulEngine *hangul) -{ - gboolean is_visible; - is_visible = lookup_table_is_visible (hangul->table); - - // Sending hide lookup table message when the lookup table - // is not visible results wrong behavior. So I have to check - // whether the table is visible or not before to hide. - if (is_visible) { - ibus_engine_hide_lookup_table ((IBusEngine *)hangul); - ibus_engine_hide_auxiliary_text ((IBusEngine *)hangul); - lookup_table_set_visible (hangul->table, FALSE); - } - - if (hangul->hanja_list != NULL) { - hanja_list_delete (hangul->hanja_list); - hangul->hanja_list = NULL; - } -} - -static void -ibus_hangul_engine_update_lookup_table (IBusHangulEngine *hangul) -{ - ibus_hangul_engine_update_hanja_list (hangul); - - if (hangul->hanja_list != NULL) { - // We should redraw preedit text with IBUS_ENGINE_PREEDIT_CLEAR option - // here to prevent committing it on focus out event incidentally. - ibus_hangul_engine_update_preedit_text (hangul); - ibus_hangul_engine_apply_hanja_list (hangul); - } else { - ibus_hangul_engine_hide_lookup_table (hangul); - } -} - -static gboolean -ibus_hangul_engine_process_candidate_key_event (IBusHangulEngine *hangul, - guint keyval, - guint modifiers) -{ - if (keyval == IBUS_Escape) { - ibus_hangul_engine_hide_lookup_table (hangul); - // When the lookup table is poped up, preedit string is - // updated with IBUS_ENGINE_PREEDIT_CLEAR option. - // So, when focus is out, the preedit text will not be committed. - // To prevent this problem, we have to update preedit text here - // with IBUS_ENGINE_PREEDIT_COMMIT option. - ibus_hangul_engine_update_preedit_text (hangul); - return TRUE; - } else if (keyval == IBUS_Return) { - ibus_hangul_engine_commit_current_candidate (hangul); - - if (hangul->hanja_mode && ibus_hangul_engine_has_preedit (hangul)) { - ibus_hangul_engine_update_lookup_table (hangul); - } else { - ibus_hangul_engine_hide_lookup_table (hangul); - } - return TRUE; - } else if (keyval >= IBUS_1 && keyval <= IBUS_9) { - guint page_no; - guint page_size; - guint cursor_pos; - - page_size = ibus_lookup_table_get_page_size (hangul->table); - cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table); - page_no = cursor_pos / page_size; - - cursor_pos = page_no * page_size + (keyval - IBUS_1); - ibus_lookup_table_set_cursor_pos (hangul->table, cursor_pos); - - ibus_hangul_engine_commit_current_candidate (hangul); - - if (hangul->hanja_mode && ibus_hangul_engine_has_preedit (hangul)) { - ibus_hangul_engine_update_lookup_table (hangul); - } else { - ibus_hangul_engine_hide_lookup_table (hangul); - } - return TRUE; - } else if (keyval == IBUS_Page_Up) { - ibus_lookup_table_page_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_Page_Down) { - ibus_lookup_table_page_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else { - if (lookup_table_orientation == 0) { - // horizontal - if (keyval == IBUS_Left) { - ibus_lookup_table_cursor_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_Right) { - ibus_lookup_table_cursor_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_Up) { - ibus_lookup_table_page_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_Down) { - ibus_lookup_table_page_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } - } else { - // vertical - if (keyval == IBUS_Left) { - ibus_lookup_table_page_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_Right) { - ibus_lookup_table_page_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_Up) { - ibus_lookup_table_cursor_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_Down) { - ibus_lookup_table_cursor_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } - } - } - - if (!hangul->hanja_mode) { - if (lookup_table_orientation == 0) { - // horizontal - if (keyval == IBUS_h) { - ibus_lookup_table_cursor_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_l) { - ibus_lookup_table_cursor_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_k) { - ibus_lookup_table_page_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_j) { - ibus_lookup_table_page_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } - } else { - // vertical - if (keyval == IBUS_h) { - ibus_lookup_table_page_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_l) { - ibus_lookup_table_page_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_k) { - ibus_lookup_table_cursor_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } else if (keyval == IBUS_j) { - ibus_lookup_table_cursor_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - return TRUE; - } - } - } - - return FALSE; -} - -static gboolean -ibus_hangul_engine_process_key_event (IBusEngine *engine, - guint keyval, - guint keycode, - guint modifiers) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - - guint mask; - gboolean retval; - const ucschar *str; - - if (modifiers & IBUS_RELEASE_MASK) - return FALSE; - - // if we don't ignore shift keys, shift key will make flush the preedit - // string. So you cannot input shift+key. - // Let's think about these examples: - // dlTek (2 set) - // qhRdmaqkq (2 set) - if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R) - return FALSE; - - // On password mode, we ignore hotkeys - if (hangul->input_purpose == IBUS_INPUT_PURPOSE_PASSWORD) - return IBUS_ENGINE_CLASS (parent_class)->process_key_event (engine, keyval, keycode, modifiers); - - // If a hotkey has any modifiers, we ignore that modifier - // keyval, or we cannot make the hanja key work. - // Because when we get the modifier key alone, we commit the - // current preedit string. So after that, even if we get the - // right hanja key event, we don't have preedit string to be changed - // to hanja word. - // See this bug: http://code.google.com/p/ibus/issues/detail?id=1036 - if (hotkey_list_has_modifier(&switch_keys, keyval)) - return FALSE; - - if (hotkey_list_match(&switch_keys, keyval, modifiers)) { - ibus_hangul_engine_switch_input_mode (hangul); - return TRUE; - } - - if (hotkey_list_match (&on_keys, keyval, modifiers)) { - ibus_hangul_engine_set_input_mode (hangul, INPUT_MODE_HANGUL); - return FALSE; - } - - if (hangul->input_mode == INPUT_MODE_LATIN) - return IBUS_ENGINE_CLASS (parent_class)->process_key_event (engine, keyval, keycode, modifiers); - - /* This feature is for vi* users. - * On Esc, the input mode is changed to latin */ - if (hotkey_list_match (&off_keys, keyval, modifiers)) { - ibus_hangul_engine_set_input_mode (hangul, INPUT_MODE_LATIN); - /* If we return TRUE, then vi will not receive "ESC" key event. */ - return FALSE; - } - - if (hotkey_list_has_modifier(&hanja_keys, keyval)) - return FALSE; - - if (hotkey_list_match(&hanja_keys, keyval, modifiers)) { - if (hangul->hanja_list == NULL) { - ibus_hangul_engine_update_lookup_table (hangul); - } else { - ibus_hangul_engine_hide_lookup_table (hangul); - } - return TRUE; - } - - if (hangul->hanja_list != NULL) { - retval = ibus_hangul_engine_process_candidate_key_event (hangul, - keyval, modifiers); - if (hangul->hanja_mode) { - if (retval) - return TRUE; - } else { - return TRUE; - } - } - - // If we've got a key event with some modifiers, commit current - // preedit string and ignore this key event. - // So, if you want to add some key event handler, put it - // before this code. - // Ignore key event with control, alt, super or mod5 - mask = IBUS_CONTROL_MASK | - IBUS_MOD1_MASK | IBUS_MOD3_MASK | IBUS_MOD4_MASK | IBUS_MOD5_MASK; - if (modifiers & mask) { - ibus_hangul_engine_flush (hangul); - return FALSE; - } - - if (keyval == IBUS_BackSpace) { - retval = hangul_ic_backspace (hangul->context); - if (!retval) { - guint preedit_len = ustring_length (hangul->preedit); - if (preedit_len > 0) { - ustring_erase (hangul->preedit, preedit_len - 1, 1); - retval = TRUE; - } - } - - ibus_hangul_engine_update_preedit_text (hangul); - - if (hangul->hanja_mode) { - if (ibus_hangul_engine_has_preedit (hangul)) { - ibus_hangul_engine_update_lookup_table (hangul); - } else { - ibus_hangul_engine_hide_lookup_table (hangul); - } - } - } else { - // We need to normalize the keyval to US qwerty keylayout, - // because the korean input method is depend on the position of - // each key, not the character. We make the keyval from keycode - // as if the keyboard is US qwerty layout. Then we can assume the - // keyval represent the position of the each key. - // But if the hic is in transliteration mode, then we should not - // normalize the keyval. - bool is_transliteration_mode = - hangul_ic_is_transliteration(hangul->context); - if (!is_transliteration_mode) { - if (keymap != NULL) - keyval = ibus_keymap_lookup_keysym(keymap, keycode, modifiers); - } - - // ignore capslock - if (modifiers & IBUS_LOCK_MASK) { - if (keyval >= 'A' && keyval <= 'z') { - if (isupper(keyval)) - keyval = tolower(keyval); - else - keyval = toupper(keyval); - } - } - retval = hangul_ic_process (hangul->context, keyval); - - str = hangul_ic_get_commit_string (hangul->context); - if (word_commit || hangul->hanja_mode) { - const ucschar* hic_preedit; - - hic_preedit = hangul_ic_get_preedit_string (hangul->context); - if (hic_preedit != NULL && hic_preedit[0] != 0) { - ustring_append_ucs4 (hangul->preedit, str, -1); - } else { - IBusText *text; - const ucschar* preedit; - - ustring_append_ucs4 (hangul->preedit, str, -1); - if (ustring_length (hangul->preedit) > 0) { - /* clear preedit text before commit */ - ibus_hangul_engine_clear_preedit_text (hangul); - - preedit = ustring_begin (hangul->preedit); - text = ibus_text_new_from_ucs4 ((gunichar*)preedit); - ibus_engine_commit_text (engine, text); - } - ustring_clear (hangul->preedit); - } - } else { - if (str != NULL && str[0] != 0) { - IBusText *text; - - /* clear preedit text before commit */ - ibus_hangul_engine_clear_preedit_text (hangul); - - text = ibus_text_new_from_ucs4 (str); - ibus_engine_commit_text (engine, text); - } - } - - ibus_hangul_engine_update_preedit_text (hangul); - - if (hangul->hanja_mode) { - ibus_hangul_engine_update_lookup_table (hangul); - } - - if (!retval) - ibus_hangul_engine_flush (hangul); - } - - /* We always return TRUE here even if we didn't use this event. - * Instead, we forward the event to clients. - * - * Because IBus has a problem with sync mode. - * I think it's limitations of IBus implementation. - * We call several engine functions(updating preedit text and committing - * text) inside this function. - * But clients cannot receive the results of other calls until this - * function ends. Clients only get one result from a remote call at a time - * because clients may run on event loop. - * Clients may process this event first and then get the results which - * may change the preedit text or commit text. - * So the event order is broken. - * Call order: - * engine client - * call process_key_event - * begin process_key_event - * call commit_text - * call update_preedit_text - * return the event as unused - * receive the result of process_key_event - * receive the result of commit_text - * receive the result of update_preedit_text - * - * To solve this problem, we return TRUE as if we consumed this event. - * After that, we forward this event to clients. - * Then clients may get the events in correct order. - * This approach is a kind of async processing. - * Call order: - * engine client - * call process_key_event - * begin process_key_event - * call commit_text - * call update_preedit_text - * call forward_key_event - * return the event as used - * receive the result of process_key_event - * receive the result of commit_text - * receive the result of update_preedit_text - * receive the forwarded key event - * - * See: https://github.com/choehwanjin/ibus-hangul/issues/40 - */ - if (use_event_forwarding) { - if (!retval) { - ibus_engine_forward_key_event (engine, keyval, keycode, modifiers); - } - - return TRUE; - } - - return retval; -} - -static void -ibus_hangul_engine_flush (IBusHangulEngine *hangul) -{ - const gunichar *str; - IBusText *text; - - ibus_hangul_engine_hide_lookup_table (hangul); - - str = hangul_ic_flush (hangul->context); - - ustring_append_ucs4 (hangul->preedit, str, -1); - - if (ustring_length (hangul->preedit) != 0) { - /* clear preedit text before commit */ - ibus_hangul_engine_clear_preedit_text (hangul); - - str = ustring_begin (hangul->preedit); - text = ibus_text_new_from_ucs4 (str); - - g_debug("flush: %s", text->text); - ibus_engine_commit_text ((IBusEngine *) hangul, text); - - ustring_clear(hangul->preedit); - } - - ibus_hangul_engine_update_preedit_text (hangul); -} - -static void -ibus_hangul_engine_focus_in (IBusEngine *engine) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - - if (hangul->input_mode == INPUT_MODE_HANGUL) { - ibus_property_set_state (hangul->prop_hangul_mode, PROP_STATE_CHECKED); - } else { - ibus_property_set_state (hangul->prop_hangul_mode, PROP_STATE_UNCHECKED); - } - - if (hangul->hanja_mode) { - ibus_property_set_state (hangul->prop_hanja_mode, PROP_STATE_CHECKED); - } else { - ibus_property_set_state (hangul->prop_hanja_mode, PROP_STATE_UNCHECKED); - } - - ibus_engine_register_properties (engine, hangul->prop_list); - - ibus_hangul_engine_update_preedit_text (hangul); - - if (hangul->hanja_list != NULL) { - ibus_hangul_engine_update_lookup_table_ui (hangul); - } - - IBUS_ENGINE_CLASS (parent_class)->focus_in (engine); -} - -static void -ibus_hangul_engine_focus_out (IBusEngine *engine) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - - if (hangul->hanja_list == NULL) { - // ibus-hangul uses - // ibus_engine_update_preedit_text_with_mode() function which makes - // the preedit string committed automatically when the focus is out. - // So we don't need to commit the preedit here. - hangul_ic_reset (hangul->context); - } else { - ibus_engine_hide_lookup_table (engine); - ibus_engine_hide_auxiliary_text (engine); - } - - IBUS_ENGINE_CLASS (parent_class)->focus_out ((IBusEngine *) hangul); -} - -static void -ibus_hangul_engine_reset (IBusEngine *engine) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - - ibus_hangul_engine_flush (hangul); - IBUS_ENGINE_CLASS (parent_class)->reset (engine); -} - -static void -ibus_hangul_engine_enable (IBusEngine *engine) -{ - IBUS_ENGINE_CLASS (parent_class)->enable (engine); - - ibus_engine_get_surrounding_text (engine, NULL, NULL, NULL); -} - -static void -ibus_hangul_engine_disable (IBusEngine *engine) -{ - ibus_hangul_engine_focus_out (engine); - IBUS_ENGINE_CLASS (parent_class)->disable (engine); -} - -static void -ibus_hangul_engine_page_up (IBusEngine *engine) -{ - IBUS_ENGINE_CLASS (parent_class)->page_up (engine); -} - -static void -ibus_hangul_engine_page_down (IBusEngine *engine) -{ - IBUS_ENGINE_CLASS (parent_class)->page_down (engine); -} - -static void -ibus_hangul_engine_cursor_up (IBusEngine *engine) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - - if (hangul->hanja_list != NULL) { - ibus_lookup_table_cursor_up (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - } - - IBUS_ENGINE_CLASS (parent_class)->cursor_up (engine); -} - -static void -ibus_hangul_engine_cursor_down (IBusEngine *engine) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - - if (hangul->hanja_list != NULL) { - ibus_lookup_table_cursor_down (hangul->table); - ibus_hangul_engine_update_lookup_table_ui (hangul); - } - - IBUS_ENGINE_CLASS (parent_class)->cursor_down (engine); -} - -static void -ibus_hangul_engine_property_activate (IBusEngine *engine, - const gchar *prop_name, - guint prop_state) -{ - if (strcmp(prop_name, "setup") == 0) { - GError *error = NULL; - gchar *argv[2] = { NULL, }; - - argv[0] = "ibus-setup-hangul"; - argv[1] = NULL; - g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error); - } else if (strcmp(prop_name, "InputMode") == 0) { - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - - ibus_hangul_engine_switch_input_mode (hangul); - } else if (strcmp(prop_name, "hanja_mode") == 0) { - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - - hangul->hanja_mode = !hangul->hanja_mode; - if (hangul->hanja_mode) { - ibus_property_set_state (hangul->prop_hanja_mode, - PROP_STATE_CHECKED); - } else { - ibus_property_set_state (hangul->prop_hanja_mode, - PROP_STATE_UNCHECKED); - } - - ibus_engine_update_property (engine, hangul->prop_hanja_mode); - ibus_hangul_engine_flush (hangul); - } -} - -static gboolean -ibus_hangul_engine_has_preedit (IBusHangulEngine *hangul) -{ - guint preedit_len; - const ucschar *hic_preedit; - - hic_preedit = hangul_ic_get_preedit_string (hangul->context); - if (hic_preedit[0] != 0) - return TRUE; - - preedit_len = ustring_length (hangul->preedit); - if (preedit_len > 0) - return TRUE; - - return FALSE; -} - -static void -ibus_hangul_engine_switch_input_mode (IBusHangulEngine *hangul) -{ - int input_mode = hangul->input_mode + 1; - - if (input_mode >= INPUT_MODE_COUNT) { - input_mode = INPUT_MODE_HANGUL; - } - - ibus_hangul_engine_set_input_mode (hangul, input_mode); -} - -static IBusText * -ibus_hangul_engine_get_input_mode_symbol (IBusHangulEngine *hangul, - int input_mode) -{ - IBusText **symbols = hangul->input_mode_symbols; - - if (symbols[0] == NULL) { - symbols[INPUT_MODE_HANGUL] = ibus_text_new_from_string ("한"); - g_object_ref_sink(symbols[INPUT_MODE_HANGUL]); - symbols[INPUT_MODE_LATIN] = ibus_text_new_from_string ("EN"); - g_object_ref_sink(symbols[INPUT_MODE_LATIN]); - } - - if (input_mode >= INPUT_MODE_COUNT) - return symbols[INPUT_MODE_HANGUL]; - - return symbols[input_mode]; -} - -static void -ibus_hangul_engine_set_input_mode (IBusHangulEngine *hangul, int input_mode) -{ - IBusText* symbol; - IBusProperty* prop; - - ibus_hangul_engine_flush (hangul); - - if (disable_latin_mode) { - return; - } - - prop = hangul->prop_hangul_mode; - - hangul->input_mode = input_mode; - g_debug("input_mode: %s", (input_mode == INPUT_MODE_HANGUL) ? "hangul" : "latin"); - - symbol = ibus_hangul_engine_get_input_mode_symbol (hangul, input_mode); - ibus_property_set_symbol(prop, symbol); - - if (hangul->input_mode == INPUT_MODE_HANGUL) { - ibus_property_set_state (prop, PROP_STATE_CHECKED); - } else { - ibus_property_set_state (prop, PROP_STATE_UNCHECKED); - } - - ibus_engine_update_property (IBUS_ENGINE (hangul), prop); -} - -static bool -ibus_hangul_engine_on_transition (HangulInputContext *hic, - ucschar c, - const ucschar *preedit, - void *data) -{ - if (!auto_reorder) { - if (hangul_is_choseong (c)) { - if (hangul_ic_has_jungseong (hic) || hangul_ic_has_jongseong (hic)) - return false; - } - - if (hangul_is_jungseong (c)) { - if (hangul_ic_has_jongseong (hic)) - return false; - } - } - - return true; -} - -static void -settings_changed (GSettings *settings, - const gchar *key, - gpointer user_data) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) user_data; - GValue schema_value = G_VALUE_INIT; - const gchar *schema_id; - GVariant *value; - - g_return_if_fail (G_IS_SETTINGS (settings)); - - g_value_init (&schema_value, G_TYPE_STRING); - g_object_get_property (G_OBJECT (settings), "schema-id", &schema_value); - schema_id = g_value_get_string (&schema_value); - value = g_settings_get_value (settings, key); - if (strcmp (schema_id, "org.freedesktop.ibus.engine.hangul") == 0) { - if (strcmp(key, "hangul-keyboard") == 0) { - const gchar *str = g_variant_get_string(value, NULL); - g_string_assign (hangul_keyboard, str); - hangul_ic_select_keyboard (hangul->context, hangul_keyboard->str); - } else if (strcmp (key, "hanja-keys") == 0) { - const gchar* str = g_variant_get_string(value, NULL); - hotkey_list_set_from_string(&hanja_keys, str); - } else if (strcmp (key, "word-commit") == 0) { - word_commit = g_variant_get_boolean (value); - } else if (strcmp (key, "auto-reorder") == 0) { - auto_reorder = g_variant_get_boolean (value); - } else if (strcmp (key, "switch-keys") == 0) { - const gchar* str = g_variant_get_string(value, NULL); - hotkey_list_set_from_string(&switch_keys, str); - } else if (strcmp (key, "on-keys") == 0) { - const gchar* str = g_variant_get_string(value, NULL); - hotkey_list_set_from_string(&on_keys, str); - } else if (strcmp (key, "off-keys") == 0) { - const gchar* str = g_variant_get_string(value, NULL); - hotkey_list_set_from_string(&off_keys, str); - } else if (strcmp (key, "initial-input-mode") == 0) { - const gchar* str = g_variant_get_string (value, NULL); - if (strcmp(str, "latin") == 0) { - initial_input_mode = INPUT_MODE_LATIN; - } else if (strcmp(str, "hangul") == 0) { - initial_input_mode = INPUT_MODE_HANGUL; - } - } - } else if (strcmp (schema_id, "org.freedesktop.ibus.panel") == 0) { - if (strcmp (key, "lookup-table-orientation") == 0) { - lookup_table_orientation = g_variant_get_int32(value); - } - } - g_variant_unref (value); - g_value_unset (&schema_value); -} - -static void -lookup_table_set_visible (IBusLookupTable *table, gboolean flag) -{ - g_object_set_data (G_OBJECT(table), "visible", GUINT_TO_POINTER(flag)); -} - -static gboolean -lookup_table_is_visible (IBusLookupTable *table) -{ - gpointer res = g_object_get_data (G_OBJECT(table), "visible"); - return GPOINTER_TO_UINT(res); -} - -static void -key_event_list_append(GArray* list, guint keyval, guint modifiers) -{ - struct KeyEvent ev = { keyval, modifiers}; - g_array_append_val(list, ev); -} - -static gboolean -key_event_list_match(GArray* list, guint keyval, guint modifiers) -{ - guint i; - guint mask; - - /* ignore capslock and numlock */ - mask = IBUS_SHIFT_MASK | - IBUS_CONTROL_MASK | - IBUS_MOD1_MASK | - IBUS_MOD3_MASK | - IBUS_MOD4_MASK | - IBUS_MOD5_MASK; - - modifiers &= mask; - for (i = 0; i < list->len; ++i) { - struct KeyEvent* ev = &g_array_index(list, struct KeyEvent, i); - if (ev->keyval == keyval && ev->modifiers == modifiers) { - return TRUE; - } - } - - return FALSE; -} - -static void -ibus_hangul_engine_candidate_clicked (IBusEngine *engine, - guint index, - guint button, - guint state) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - if (hangul == NULL) - return; - - if (hangul->table == NULL) - return; - - ibus_lookup_table_set_cursor_pos (hangul->table, index); - ibus_hangul_engine_commit_current_candidate (hangul); - - if (hangul->hanja_mode) { - ibus_hangul_engine_update_lookup_table (hangul); - } else { - ibus_hangul_engine_hide_lookup_table (hangul); - } -} - -static void -ibus_hangul_engine_set_content_type (IBusEngine *engine, - guint purpose, - guint hints) -{ - IBusHangulEngine *hangul = (IBusHangulEngine *) engine; - if (hangul == NULL) - return; - - hangul->input_purpose = purpose; -} - -static void -hotkey_list_init(HotkeyList* list) -{ - list->all_modifiers = 0; - list->keys = g_array_sized_new(FALSE, TRUE, sizeof(struct KeyEvent), 4); -} - -static void -hotkey_list_fini(HotkeyList* list) -{ - g_array_free(list->keys, TRUE); - list->keys = NULL; -} - -static void -hotkey_list_append_from_string(HotkeyList *list, const char* str) -{ - guint keyval = 0; - guint modifiers = 0; - gboolean res; - - res = ibus_key_event_from_string(str, &keyval, &modifiers); - if (res) { - hotkey_list_append(list, keyval, modifiers); - } -} - -static void -hotkey_list_append(HotkeyList *list, guint keyval, guint modifiers) -{ - list->all_modifiers |= modifiers; - key_event_list_append(list->keys, keyval, modifiers); -} - -static void -hotkey_list_set_from_string(HotkeyList *list, const char* str) -{ - gchar** items = g_strsplit(str, ",", 0); - - list->all_modifiers = 0; - g_array_set_size(list->keys, 0); - - if (items != NULL) { - int i; - for (i = 0; items[i] != NULL; ++i) { - hotkey_list_append_from_string(list, items[i]); - } - g_strfreev(items); - } -} - -static gboolean -hotkey_list_match(HotkeyList* list, guint keyval, guint modifiers) -{ - return key_event_list_match(list->keys, keyval, modifiers); -} - -static gboolean -hotkey_list_has_modifier(HotkeyList* list, guint keyval) -{ - if (list->all_modifiers & IBUS_CONTROL_MASK) { - if (keyval == IBUS_Control_L || keyval == IBUS_Control_R) - return TRUE; - } - - if (list->all_modifiers & IBUS_MOD1_MASK) { - if (keyval == IBUS_Alt_L || keyval == IBUS_Alt_R) - return TRUE; - } - - if (list->all_modifiers & IBUS_SUPER_MASK) { - if (keyval == IBUS_Super_L || keyval == IBUS_Super_R) - return TRUE; - } - - if (list->all_modifiers & IBUS_HYPER_MASK) { - if (keyval == IBUS_Hyper_L || keyval == IBUS_Hyper_R) - return TRUE; - } - - if (list->all_modifiers & IBUS_META_MASK) { - if (keyval == IBUS_Meta_L || keyval == IBUS_Meta_R) - return TRUE; - } - - return FALSE; -}