summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChoe Hwanjin <choe.hwanjin@gmail.com>2012-01-05 23:49:56 +0900
committerChoe Hwanjin <choe.hwanjin@gmail.com>2012-01-05 23:49:56 +0900
commit28d85c9309131a5981f65fe2d911b622d2f2de9b (patch)
tree388d87c5fd5248dc44bb0e3768de1dc2cf490749 /src
parent8d3735e4f303ed57141257b6934a560ebcedeec6 (diff)
downloadibus-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.c204
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,