Exemplo n.º 1
0
static gboolean
nimf_libhangul_filter_leading_consonant (NimfEngine    *engine,
                                         NimfServiceIC *target,
                                         guint          keyval)
{
  g_debug (G_STRLOC ": %s", G_STRFUNC);

  NimfLibhangul *hangul = NIMF_LIBHANGUL (engine);

  const ucschar *ucs_preedit;
  ucs_preedit = hangul_ic_get_preedit_string (hangul->context);

  /* check ㄱ ㄷ ㅂ ㅅ ㅈ */
  if ((keyval == 'r' && ucs_preedit[0] == 0x3131 && ucs_preedit[1] == 0) ||
      (keyval == 'e' && ucs_preedit[0] == 0x3137 && ucs_preedit[1] == 0) ||
      (keyval == 'q' && ucs_preedit[0] == 0x3142 && ucs_preedit[1] == 0) ||
      (keyval == 't' && ucs_preedit[0] == 0x3145 && ucs_preedit[1] == 0) ||
      (keyval == 'w' && ucs_preedit[0] == 0x3148 && ucs_preedit[1] == 0))
  {
    gchar *preedit = g_ucs4_to_utf8 (ucs_preedit, -1, NULL, NULL, NULL);
    nimf_libhangul_emit_commit (engine, target, preedit);
    g_free (preedit);
    nimf_engine_emit_preedit_changed (engine, target, hangul->preedit_string,
                                      hangul->preedit_attrs,
                                      g_utf8_strlen (hangul->preedit_string,
                                                     -1));
    return TRUE;
  }

  return FALSE;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
static bool
check_preedit_with_ic(HangulInputContext* ic, const char* input, const wchar_t* output)
{
    const char* p;
    const ucschar* preedit;
    int res;

    p = input;
    while (*p != '\0') {
	hangul_ic_process(ic, *p);
	p++;
    }

    preedit = hangul_ic_get_preedit_string(ic);

    res = wcscmp((const wchar_t*)preedit, output);

    return res == 0;
}
Exemplo n.º 5
0
static PyObject *_pyhangulic_preedit_string(PY_HANGULIC *self, PyObject *args)
{
#ifndef Py_UNICODE_WIDE
    int i;
    Py_UNICODE *buf;
#endif /* !Py_UNICODE_WIDE */
    int len;
    const ucschar *str;

    str = hangul_ic_get_preedit_string(self->hic);
    len = ucscharlen(str);

#ifdef Py_UNICODE_WIDE
    return PyUnicode_FromUnicode((Py_UNICODE*)str, len);
#else  /* Py_UNICODE_WIDE */
    buf = alloca(sizeof(Py_UNICODE) * len);
    for (i = 0; i < len; i++)
	buf[i] = str[i];
    return PyUnicode_FromUnicode(buf, len);
#endif /* Py_UNICODE_WIDE */
}
bool QHangulPlatformInputContext::popupCandidateList() {
    const ucschar *text = hangul_ic_get_preedit_string(m_hic);
    if (text != NULL && *text != 0) {
	QString str;
	str += QChar(text[0]);
	HanjaList *list = hanja_table_match_suffix(hanjaTable, str.toUtf8());

	if (m_candidateList == NULL)
	    m_candidateList = new CandidateList();

	QPoint p(0, 0);

	QWidget *focus = qobject_cast<QWidget *>(m_focusObject);
	if (focus != NULL) {
	    QVariant v = focus->inputMethodQuery(Qt::ImMicroFocus);
	    QRect r = v.toRect();
	    p = focus->mapToGlobal(QPoint(r.right(), r.bottom()));
	}

	m_candidateList->open(list, p.x(), p.y());
    }

    return false;
}
QString QHangulPlatformInputContext::getPreeditString() const {
    return ucsToQString(hangul_ic_get_preedit_string(m_hic));
}
Exemplo n.º 8
0
END_TEST

START_TEST(test_hangul_ic_process_romaja)
{
    HangulInputContext* ic;
    const ucschar* preedit;
    const ucschar* commit;

    // romaja keyboard test
    ic = hangul_ic_new("ro");

    // basic test: han produces 한
    hangul_ic_process(ic, 'h');
    hangul_ic_process(ic, 'a');
    hangul_ic_process(ic, 'n');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == L'한');
    fail_unless(commit[0] == 0);

    hangul_ic_reset(ic);

    // insert ㅇ when a syllable is not started with consonant
    hangul_ic_process(ic, 'a');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == L'아');
    fail_unless(commit[0] == 0);

    // remove correctly when automatically ㅇ was inserted
    hangul_ic_backspace(ic);

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == 0);
    fail_unless(commit[0] == 0);

    // append ㅡ when a syllable is not ended with vowel
    hangul_ic_process(ic, 't');
    hangul_ic_process(ic, 't');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == 0x314c); // ㅌ
    fail_unless(commit[0] == L'트');

    // ng makes trailing ㅇ
    hangul_ic_reset(ic);
    hangul_ic_process(ic, 'g');
    hangul_ic_process(ic, 'a');
    hangul_ic_process(ic, 'n');
    hangul_ic_process(ic, 'g');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == L'강'); // 강
    fail_unless(commit[0] == 0);

    // gangi makes 강이
    hangul_ic_process(ic, 'i');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == L'이');
    fail_unless(commit[0] == L'강');  // 강

    // nanG makes 난ㄱ
    // uppercase makes new syllable
    hangul_ic_process(ic, 'n');
    hangul_ic_process(ic, 'a');
    hangul_ic_process(ic, 'n');
    hangul_ic_process(ic, 'G');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == 0x3131); // ㄱ
    fail_unless(commit[0] == L'난');  // 난

    // special operation for x
    // x generate ㅈ for leading consonant
    hangul_ic_reset(ic);
    hangul_ic_process(ic, 'x');
    hangul_ic_process(ic, 'x');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == 0x3148); // 지
    fail_unless(commit[0] == L'즈');

    hangul_ic_reset(ic);
    hangul_ic_process(ic, 'x');
    hangul_ic_process(ic, 'y');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == L'지'); // 지
    fail_unless(commit[0] == 0x0);

    // x generate ㄱㅅ for trailing consonant
    // and ㅅ will be transferred to next syllable when next input
    // character is vowel.
    hangul_ic_reset(ic);
    hangul_ic_process(ic, 's');
    hangul_ic_process(ic, 'e');
    hangul_ic_process(ic, 'x');
    hangul_ic_process(ic, 'y');

    preedit = hangul_ic_get_preedit_string(ic);
    commit = hangul_ic_get_commit_string(ic);
    fail_unless(preedit[0] == L'시'); // 시
    fail_unless(commit[0] == L'섹');  // 섹
    
    hangul_ic_delete(ic);
}
Exemplo n.º 9
0
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;

    // If hanja key 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 (hanja_key_list_has_modifier(&hanja_keys, keyval))
	return FALSE; 

    if (hanja_key_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);
    }

    return retval;
}
Exemplo n.º 10
0
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);
}
Exemplo n.º 11
0
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);
}
Exemplo n.º 12
0
gboolean
nimf_libhangul_filter_event (NimfEngine    *engine,
                             NimfServiceIC *target,
                             NimfEvent     *event)
{
  g_debug (G_STRLOC ": %s", G_STRFUNC);

  guint    keyval;
  gboolean retval = FALSE;

  NimfLibhangul *hangul = NIMF_LIBHANGUL (engine);

  if (event->key.type   == NIMF_EVENT_KEY_RELEASE ||
      event->key.keyval == NIMF_KEY_Shift_L       ||
      event->key.keyval == NIMF_KEY_Shift_R)
    return FALSE;

  if (event->key.state & (NIMF_CONTROL_MASK | NIMF_MOD1_MASK))
  {
    nimf_libhangul_reset (engine, target);
    return FALSE;
  }

  if (G_UNLIKELY (nimf_event_matches (event,
                  (const NimfKey **) hangul->hanja_keys)))
  {
    if (nimf_candidatable_is_visible (hangul->candidatable) == FALSE)
    {
      gchar item[4];
      const char *key = hangul->preedit_string;
      gboolean use_preedit;

      if (hangul->preedit_string[0] == 0)
      {
        gchar *text;
        gint   cursor_pos;

        nimf_engine_get_surrounding (engine, target, &text, &cursor_pos);

        if (text && cursor_pos > 0)
        {
          gchar *p = g_utf8_offset_to_pointer (text, cursor_pos - 1);
          g_utf8_strncpy (item, p, 1);

          if (g_utf8_validate (item, -1, NULL))
            key = item;
        }

        g_free (text);
      }

      hanja_list_delete (hangul->hanja_list);
      nimf_candidatable_clear (hangul->candidatable, target);
      hangul->hanja_list = hanja_table_match_exact (nimf_libhangul_hanja_table, key);

      if (hangul->hanja_list == NULL)
        hangul->hanja_list = hanja_table_match_exact (nimf_libhangul_symbol_table, key);

      hangul->n_pages = (hanja_list_get_size (hangul->hanja_list) + 9) / 10;
      hangul->current_page = 1;
      nimf_libhangul_update_page (engine, target);
      use_preedit = nimf_service_ic_get_use_preedit (target);

      if (!use_preedit)
        nimf_candidatable_set_auxiliary_text (hangul->candidatable,
                                              key, g_utf8_strlen (key, -1));

      nimf_candidatable_show (hangul->candidatable, target, !use_preedit);
      nimf_candidatable_select_first_item_in_page (hangul->candidatable);
    }
    else
    {
      nimf_candidatable_hide (hangul->candidatable);
      nimf_candidatable_clear (hangul->candidatable, target);
      hanja_list_delete (hangul->hanja_list);
      hangul->hanja_list = NULL;
      hangul->current_page = 0;
      hangul->n_pages = 0;
    }

    return TRUE;
  }

  if (nimf_candidatable_is_visible (hangul->candidatable))
  {
    switch (event->key.keyval)
    {
      case NIMF_KEY_Return:
      case NIMF_KEY_KP_Enter:
        {
          gchar *text;

          text = nimf_candidatable_get_selected_text (hangul->candidatable);
          on_candidate_clicked (engine, target, text, -1);

          g_free (text);
        }
        break;
      case NIMF_KEY_Up:
      case NIMF_KEY_KP_Up:
        nimf_candidatable_select_previous_item (hangul->candidatable);
        break;
      case NIMF_KEY_Down:
      case NIMF_KEY_KP_Down:
        nimf_candidatable_select_next_item (hangul->candidatable);
        break;
      case NIMF_KEY_Page_Up:
      case NIMF_KEY_KP_Page_Up:
        nimf_libhangul_page_up (engine, target);
        break;
      case NIMF_KEY_Page_Down:
      case NIMF_KEY_KP_Page_Down:
        nimf_libhangul_page_down (engine, target);
        break;
      case NIMF_KEY_Home:
        nimf_libhangul_page_home (engine, target);
        break;
      case NIMF_KEY_End:
        nimf_libhangul_page_end (engine, target);
        break;
      case NIMF_KEY_Escape:
        nimf_candidatable_hide (hangul->candidatable);
        break;
      case NIMF_KEY_0:
      case NIMF_KEY_1:
      case NIMF_KEY_2:
      case NIMF_KEY_3:
      case NIMF_KEY_4:
      case NIMF_KEY_5:
      case NIMF_KEY_6:
      case NIMF_KEY_7:
      case NIMF_KEY_8:
      case NIMF_KEY_9:
      case NIMF_KEY_KP_0:
      case NIMF_KEY_KP_1:
      case NIMF_KEY_KP_2:
      case NIMF_KEY_KP_3:
      case NIMF_KEY_KP_4:
      case NIMF_KEY_KP_5:
      case NIMF_KEY_KP_6:
      case NIMF_KEY_KP_7:
      case NIMF_KEY_KP_8:
      case NIMF_KEY_KP_9:
        {
          if (hangul->hanja_list == NULL || hangul->current_page < 1)
            break;

          gint i, n;
          gint list_len = hanja_list_get_size (hangul->hanja_list);

          if (event->key.keyval >= NIMF_KEY_0 &&
              event->key.keyval <= NIMF_KEY_9)
            n = (event->key.keyval - NIMF_KEY_0 + 9) % 10;
          else if (event->key.keyval >= NIMF_KEY_KP_0 &&
                   event->key.keyval <= NIMF_KEY_KP_9)
            n = (event->key.keyval - NIMF_KEY_KP_0 + 9) % 10;
          else
            break;

          i = (hangul->current_page - 1) * 10 + n;

          if (i < MIN (hangul->current_page * 10, list_len))
          {
            const Hanja *hanja = hanja_list_get_nth (hangul->hanja_list, i);
            const char  *text = hanja_get_value (hanja);
            on_candidate_clicked (engine, target, (gchar *) text, -1);
          }
        }
        break;
      default:
        break;
    }

    return TRUE;
  }

  const ucschar *ucs_commit;
  const ucschar *ucs_preedit;

  if (G_UNLIKELY (event->key.keyval == NIMF_KEY_BackSpace))
  {
    retval = hangul_ic_backspace (hangul->context);

    if (retval)
    {
      ucs_preedit = hangul_ic_get_preedit_string (hangul->context);
      gchar *new_preedit = g_ucs4_to_utf8 (ucs_preedit, -1, NULL, NULL, NULL);
      nimf_libhangul_update_preedit (engine, target, new_preedit);
    }

    return retval;
  }

  if (G_UNLIKELY (g_strcmp0 (hangul->method, "ro") == 0))
    keyval = event->key.keyval;
  else
    keyval = nimf_event_keycode_to_qwerty_keyval (event);

  if (!hangul->is_double_consonant_rule &&
      (g_strcmp0 (hangul->method, "2") == 0) &&
      nimf_libhangul_filter_leading_consonant (engine, target, keyval))
    return TRUE;

  retval = hangul_ic_process (hangul->context, keyval);

  ucs_commit  = hangul_ic_get_commit_string  (hangul->context);
  ucs_preedit = hangul_ic_get_preedit_string (hangul->context);

  gchar *new_commit  = g_ucs4_to_utf8 (ucs_commit,  -1, NULL, NULL, NULL);

  if (ucs_commit[0] != 0)
    nimf_libhangul_emit_commit (engine, target, new_commit);

  g_free (new_commit);

  gchar *new_preedit = g_ucs4_to_utf8 (ucs_preedit, -1, NULL, NULL, NULL);
  nimf_libhangul_update_preedit (engine, target, new_preedit);

  return retval;
}