diff options
author | Choe Hwanjin <choe.hwanjin@gmail.com> | 2012-01-05 23:49:56 +0900 |
---|---|---|
committer | Choe Hwanjin <choe.hwanjin@gmail.com> | 2012-01-05 23:49:56 +0900 |
commit | 28d85c9309131a5981f65fe2d911b622d2f2de9b (patch) | |
tree | 388d87c5fd5248dc44bb0e3768de1dc2cf490749 /src | |
parent | 8d3735e4f303ed57141257b6934a560ebcedeec6 (diff) | |
download | ibus-hangul-28d85c9309131a5981f65fe2d911b622d2f2de9b.tar.gz |
Add text conversion feature using surrounding text
This patch implements text conversion feature.
With surrounding text, ibus-hangul can convert text that is
already commited or pasted to hanja string.
Diffstat (limited to 'src')
-rw-r--r-- | src/engine.c | 204 |
1 files changed, 187 insertions, 17 deletions
diff --git a/src/engine.c b/src/engine.c index 7203683..61048e3 100644 --- a/src/engine.c +++ b/src/engine.c @@ -67,6 +67,12 @@ struct _HanjaKeyList { GArray *keys; }; +enum { + LOOKUP_METHOD_EXACT, + LOOKUP_METHOD_PREFIX, + LOOKUP_METHOD_SUFFIX, +}; + /* functions prototype */ static void ibus_hangul_engine_class_init (IBusHangulEngineClass *klass); @@ -127,6 +133,9 @@ static void ibus_hangul_engine_update_preedit_text static void ibus_hangul_engine_update_lookup_table (IBusHangulEngine *hangul); +static gboolean ibus_hangul_engine_has_preedit + (IBusHangulEngine *hangul); + static void ibus_config_value_changed (IBusConfig *config, const gchar *section, const gchar *name, @@ -155,6 +164,8 @@ static gboolean hanja_key_list_match (HanjaKeyList *list, static gboolean hanja_key_list_has_modifier (HanjaKeyList *list, guint keyval); +static glong ucschar_strlen (const ucschar* str); + static IBusEngineClass *parent_class = NULL; static HanjaTable *hanja_table = NULL; static HanjaTable *symbol_table = NULL; @@ -164,6 +175,15 @@ static HanjaKeyList hanja_keys; static int lookup_table_orientation = 0; static IBusKeymap *keymap = NULL; +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) { @@ -442,23 +462,42 @@ ibus_hangul_engine_commit_current_candidate (IBusHangulEngine *hangul) guint cursor_pos; const char* key; const char* value; - int key_len; - int preedit_len; - int len; + 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); - len = MIN(key_len, preedit_len); - ustring_erase (hangul->preedit, 0, len); - if (key_len > preedit_len) + /* 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); + } ibus_hangul_engine_update_preedit_text (hangul); @@ -466,12 +505,87 @@ ibus_hangul_engine_commit_current_candidate (IBusHangulEngine *hangul) ibus_engine_commit_text ((IBusEngine *)hangul, text); } +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; + + 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) { - char* utf8; + 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); @@ -480,22 +594,59 @@ ibus_hangul_engine_update_hanja_list (IBusHangulEngine *hangul) 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) { - utf8 = ustring_to_utf8 (preedit, -1); - if (utf8 != NULL) { - if (symbol_table != NULL) - hangul->hanja_list = hanja_table_match_prefix (symbol_table, utf8); - if (hangul->hanja_list == NULL) - hangul->hanja_list = hanja_table_match_prefix (hanja_table, utf8); - g_free (utf8); + preedit_utf8 = ustring_to_utf8 (preedit, -1); + if (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); + 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) @@ -571,7 +722,7 @@ ibus_hangul_engine_process_candidate_key_event (IBusHangulEngine *hangul, } else if (keyval == IBUS_Return) { ibus_hangul_engine_commit_current_candidate (hangul); - if (hangul->hanja_mode) { + 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); @@ -591,7 +742,7 @@ ibus_hangul_engine_process_candidate_key_event (IBusHangulEngine *hangul, ibus_hangul_engine_commit_current_candidate (hangul); - if (hangul->hanja_mode) { + 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); @@ -902,6 +1053,8 @@ static void ibus_hangul_engine_enable (IBusEngine *engine) { parent_class->enable (engine); + + ibus_engine_get_surrounding_text (engine, NULL, NULL, NULL); } static void @@ -978,6 +1131,23 @@ ibus_hangul_engine_property_activate (IBusEngine *engine, } } +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_config_value_changed (IBusConfig *config, const gchar *section, |