Implement hanja conversion feature
authorChoe Hwanjin <choe.hwanjin@gmail.com>
Sat, 28 Feb 2009 11:51:35 +0000 (20:51 +0900)
committerChoe Hwanjin <choe.hwanjin@gmail.com>
Sat, 28 Feb 2009 11:51:35 +0000 (20:51 +0900)
src/engine.c
src/engine.h
src/main.c

index c0e1028..0900361 100644 (file)
@@ -14,6 +14,7 @@ struct _IBusHangulEngine {
     /* members */
     HangulInputContext *context;
     gboolean hangul_mode;
+    HanjaList* hanja_list;
 
     IBusLookupTable *table;
     IBusProperty    *hangul_mode_prop;
@@ -75,6 +76,7 @@ static void ibus_hangul_engine_update_preedit_text
                                             (IBusHangulEngine       *hangul);
 
 static IBusEngineClass *parent_class = NULL;
+static HanjaTable *hanja_table = NULL;
 
 GType
 ibus_hangul_engine_get_type (void)
@@ -103,6 +105,18 @@ ibus_hangul_engine_get_type (void)
        return type;
 }
 
+void
+ibus_hangul_init (void)
+{
+    hanja_table = hanja_table_load (NULL);
+}
+
+void
+ibus_hangul_exit (void)
+{
+    hanja_table_delete (hanja_table);
+}
+
 static void
 ibus_hangul_engine_class_init (IBusHangulEngineClass *klass)
 {
@@ -135,6 +149,7 @@ static void
 ibus_hangul_engine_init (IBusHangulEngine *hangul)
 {
     hangul->context = hangul_ic_new ("2");
+    hangul->hanja_list = NULL;
     hangul->hangul_mode = TRUE;
     hangul->hangul_mode_prop = ibus_property_new ("hangul_mode_prop",
                                            PROP_TYPE_NORMAL,
@@ -149,7 +164,7 @@ ibus_hangul_engine_init (IBusHangulEngine *hangul)
     hangul->prop_list = ibus_prop_list_new ();
     ibus_prop_list_append (hangul->prop_list,  hangul->hangul_mode_prop);
 
-    hangul->table = ibus_lookup_table_new (9, 0, TRUE, TRUE);
+    hangul->table = ibus_lookup_table_new (9, 0, TRUE, FALSE);
 }
 
 static GObject*
@@ -218,6 +233,166 @@ ibus_hangul_engine_update_preedit_text (IBusHangulEngine *hangul)
     }
 }
 
+static void
+ibus_hangul_engine_update_auxiliary_text (IBusHangulEngine *hangul)
+{
+    guint cursor_pos;
+    const char* comment;
+    IBusText* 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);
+    g_object_unref (text);
+}
+
+static void
+ibus_hangul_engine_update_lookup_table (IBusHangulEngine *hangul)
+{
+    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* value;
+    IBusText* text;
+
+    hangul_ic_reset (hangul->context);
+    ibus_hangul_engine_update_preedit_text (hangul);
+
+    cursor_pos = ibus_lookup_table_get_cursor_pos (hangul->table);
+    value = hanja_list_get_nth_value (hangul->hanja_list, cursor_pos);
+
+    text = ibus_text_new_from_string (value);
+    ibus_engine_commit_text ((IBusEngine *)hangul, text);
+    g_object_unref (text);
+}
+
+static void
+ibus_hangul_engine_open_lookup_table (IBusHangulEngine *hangul)
+{
+    char* utf8;
+    const gunichar* str;
+
+    str = hangul_ic_get_preedit_string (hangul->context);
+    utf8 = g_ucs4_to_utf8 (str, -1, NULL, NULL, NULL);
+    if (utf8 != NULL) {
+        HanjaList* list = hanja_table_match_suffix (hanja_table, utf8);
+        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);
+                g_object_unref (text);
+            }
+
+            hanja_list_delete (hangul->hanja_list);
+            hangul->hanja_list = list;
+
+            ibus_lookup_table_set_cursor_pos (hangul->table, 0);
+            ibus_hangul_engine_update_auxiliary_text (hangul);
+            ibus_hangul_engine_update_lookup_table (hangul);
+        }
+        g_free (utf8);
+    }
+}
+
+static void
+ibus_hangul_engine_close_lookup_table (IBusHangulEngine *hangul)
+{
+    ibus_engine_hide_lookup_table ((IBusEngine *)hangul);
+    ibus_engine_hide_auxiliary_text ((IBusEngine *)hangul);
+    hanja_list_delete (hangul->hanja_list);
+    hangul->hanja_list = NULL;
+}
+
+static void
+ibus_hangul_engine_toggle_lookup_table (IBusHangulEngine *hangul)
+{
+    if (hangul->hanja_list != NULL) {
+        ibus_hangul_engine_close_lookup_table (hangul);
+    } else {
+        ibus_hangul_engine_open_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_close_lookup_table (hangul);
+    } else if (keyval == IBUS_Return) {
+       ibus_hangul_engine_commit_current_candidate (hangul);
+        ibus_hangul_engine_close_lookup_table (hangul);
+    } 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);
+        ibus_hangul_engine_close_lookup_table (hangul);
+    } else if (keyval == IBUS_Left) {
+        ibus_lookup_table_cursor_up (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_Right) {
+        ibus_lookup_table_cursor_down (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_Up) {
+        ibus_lookup_table_page_up (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_Down) {
+        ibus_lookup_table_page_down (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_Page_Up) {
+        ibus_lookup_table_page_up (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_Page_Down) {
+        ibus_lookup_table_page_down (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_h) {
+        ibus_lookup_table_cursor_up (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_l) {
+        ibus_lookup_table_cursor_down (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_k) {
+        ibus_lookup_table_page_up (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    } else if (keyval == IBUS_j) {
+        ibus_lookup_table_page_down (hangul->table);
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    }
+
+    return TRUE;
+}
+
 static gboolean
 ibus_hangul_engine_process_key_event (IBusEngine     *engine,
                                       guint           keyval,
@@ -231,9 +406,6 @@ ibus_hangul_engine_process_key_event (IBusEngine     *engine,
     if (modifiers & IBUS_RELEASE_MASK)
         return FALSE;
 
-    if (modifiers & (IBUS_CONTROL_MASK | IBUS_MOD1_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:
@@ -242,6 +414,19 @@ ibus_hangul_engine_process_key_event (IBusEngine     *engine,
     if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R)
         return FALSE;
 
+    if (keyval == IBUS_F9 || keyval == IBUS_Hangul_Hanja) {
+       ibus_hangul_engine_toggle_lookup_table (hangul);
+       return TRUE;
+    }
+
+    if (modifiers & (IBUS_CONTROL_MASK | IBUS_MOD1_MASK))
+        return FALSE;
+
+    if (hangul->hanja_list != NULL) {
+        return ibus_hangul_engine_process_candidate_key_event (hangul,
+                     keyval, modifiers);
+    }
+
     if (keyval == IBUS_BackSpace) {
         retval = hangul_ic_backspace (hangul->context);
     } else {
@@ -309,6 +494,11 @@ ibus_hangul_engine_focus_in (IBusEngine *engine)
 
     ibus_engine_register_properties (engine, hangul->prop_list);
 
+    if (hangul->hanja_list != NULL) {
+        ibus_hangul_engine_update_lookup_table (hangul);
+        ibus_hangul_engine_update_auxiliary_text (hangul);
+    }
+
     parent_class->focus_in (engine);
 }
 
@@ -317,7 +507,12 @@ ibus_hangul_engine_focus_out (IBusEngine *engine)
 {
     IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
 
-    ibus_hangul_engine_flush (hangul);
+    if (hangul->hanja_list == NULL) {
+       ibus_hangul_engine_flush (hangul);
+    } else {
+       ibus_engine_hide_lookup_table (engine);
+       ibus_engine_hide_auxiliary_text (engine);
+    }
 
     parent_class->focus_out ((IBusEngine *) hangul);
 }
@@ -328,6 +523,9 @@ ibus_hangul_engine_reset (IBusEngine *engine)
     IBusHangulEngine *hangul = (IBusHangulEngine *) engine;
 
     ibus_hangul_engine_flush (hangul);
+    if (hangul->hanja_list != NULL) {
+        ibus_hangul_engine_close_lookup_table (hangul);
+    }
     parent_class->reset (engine);
 }
 
@@ -359,12 +557,28 @@ ibus_hangul_engine_page_down (IBusEngine *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 (hangul);
+       ibus_hangul_engine_update_auxiliary_text (hangul);
+    }
+
     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 (hangul);
+       ibus_hangul_engine_update_auxiliary_text (hangul);
+    }
+
     parent_class->cursor_down (engine);
 }
 
index 8ecfeb9..1bbdabe 100644 (file)
@@ -9,4 +9,7 @@
 
 GType   ibus_hangul_engine_get_type    (void);
 
+void    ibus_hangul_init (void);
+void    ibus_hangul_exit (void);
+
 #endif
index 654a458..48aa3ef 100644 (file)
@@ -38,6 +38,7 @@ start_component (void)
     IBusComponent *component;
 
     ibus_init ();
+    ibus_hangul_init ();
 
     bus = ibus_bus_new ();
     g_signal_connect (bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL);
@@ -74,6 +75,8 @@ start_component (void)
     g_object_unref (component);
 
     ibus_main ();
+
+    ibus_hangul_exit ();
 }
 
 int