--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/textinput/ptihangulcore/src/hangulinputcontext.c Sun Mar 14 13:11:12 2010 +0000
@@ -0,0 +1,1232 @@
+/* libhangul
+ * Copyright (c) 2005,2006 Choe Hwanjin
+ * All rights reserved.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+
+#include "hangul.h"
+#include "hangulinternals.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define HANGUL_KEYBOARD_TABLE_SIZE 0x80
+
+typedef void (*HangulOnTranslate) (HangulInputContext*,
+ int,
+ ucschar*,
+ void*);
+typedef bool (*HangulOnTransition) (HangulInputContext*,
+ ucschar,
+ const ucschar*,
+ void*);
+
+typedef struct _HangulCombinationItem HangulCombinationItem;
+
+struct _HangulKeyboard {
+ int type;
+ ucschar* table;
+};
+
+struct _HangulCombinationItem {
+ uint32_t key;
+ ucschar code;
+};
+
+struct _HangulCombination {
+ int size;
+ HangulCombinationItem *table;
+};
+
+struct _HangulBuffer {
+ ucschar choseong;
+ ucschar jungseong;
+ ucschar jongseong;
+
+ ucschar stack[12];
+ int index;
+};
+
+struct _HangulInputContext {
+ int type;
+
+ const HangulKeyboard* keyboard;
+ const HangulCombination* combination;
+
+ HangulBuffer buffer;
+ int output_mode;
+
+ ucschar preedit_string[64];
+ ucschar commit_string[64];
+ ucschar flushed_string[64];
+
+ HangulOnTranslate on_translate;
+ void* on_translate_data;
+
+ HangulOnTransition on_transition;
+ void* on_transition_data;
+
+ HangulICFilter filter;
+ void *filter_data;
+
+ unsigned int use_jamo_mode_only : 1;
+};
+
+#include "hangulkeyboard.h"
+
+static const HangulKeyboard hangul_keyboard_2 = {
+ HANGUL_KEYBOARD_TYPE_JAMO,
+ (ucschar*)hangul_keyboard_table_2
+};
+
+static const HangulKeyboard hangul_keyboard_32 = {
+ HANGUL_KEYBOARD_TYPE_JASO,
+ (ucschar*)hangul_keyboard_table_32
+};
+
+static const HangulKeyboard hangul_keyboard_390 = {
+ HANGUL_KEYBOARD_TYPE_JASO,
+ (ucschar*)hangul_keyboard_table_390
+};
+
+static const HangulKeyboard hangul_keyboard_3final = {
+ HANGUL_KEYBOARD_TYPE_JASO,
+ (ucschar*)hangul_keyboard_table_3final
+};
+
+static const HangulKeyboard hangul_keyboard_3sun = {
+ HANGUL_KEYBOARD_TYPE_JASO,
+ (ucschar*)hangul_keyboard_table_3sun
+};
+
+static const HangulKeyboard hangul_keyboard_3yet = {
+ HANGUL_KEYBOARD_TYPE_JASO,
+ (ucschar*)hangul_keyboard_table_3yet
+};
+
+static const HangulCombination hangul_combination_default = {
+ N_ELEMENTS(hangul_combination_table_default),
+ (HangulCombinationItem*)hangul_combination_table_default
+};
+
+static const HangulCombination hangul_combination_full = {
+ N_ELEMENTS(hangul_combination_table_full),
+ (HangulCombinationItem*)hangul_combination_table_full
+};
+
+static void hangul_buffer_push(HangulBuffer *buffer, ucschar ch);
+static ucschar hangul_buffer_pop (HangulBuffer *buffer);
+static ucschar hangul_buffer_peek(HangulBuffer *buffer);
+
+static void hangul_buffer_clear(HangulBuffer *buffer);
+static int hangul_buffer_get_string(HangulBuffer *buffer, ucschar*buf, int buflen);
+static int hangul_buffer_get_jamo_string(HangulBuffer *buffer, ucschar *buf, int buflen);
+
+static void hangul_ic_flush_internal(HangulInputContext *hic);
+
+HangulKeyboard*
+hangul_keyboard_new()
+{
+ HangulKeyboard *keyboard = malloc(sizeof(HangulKeyboard));
+ if (keyboard != NULL) {
+ keyboard->table = malloc(sizeof(ucschar) * HANGUL_KEYBOARD_TABLE_SIZE);
+ if (keyboard->table != NULL) {
+ int i;
+ for (i = 0; i < HANGUL_KEYBOARD_TABLE_SIZE; i++)
+ keyboard->table[i] = 0;
+
+ return keyboard;
+ }
+ free(keyboard);
+ }
+
+ return NULL;
+}
+
+static ucschar
+hangul_keyboard_get_value(const HangulKeyboard *keyboard, int key)
+{
+ if (keyboard != NULL) {
+ if (key >= 0 && key < HANGUL_KEYBOARD_TABLE_SIZE)
+ return keyboard->table[key];
+ }
+
+ return 0;
+}
+
+void
+hangul_keyboard_set_value(HangulKeyboard *keyboard, int key, ucschar value)
+{
+ if (keyboard != NULL) {
+ if (key >= 0 && key < N_ELEMENTS(keyboard->table))
+ keyboard->table[key] = value;
+ }
+}
+
+static int
+hangul_keyboard_get_type(const HangulKeyboard *keyboard)
+{
+ int type = 0;
+ if (keyboard != NULL) {
+ type = keyboard->type;
+ }
+ return type;
+}
+
+void
+hangul_keyboard_set_type(HangulKeyboard *keyboard, int type)
+{
+ if (keyboard != NULL) {
+ keyboard->type = type;
+ }
+}
+
+void
+hangul_keyboard_delete(HangulKeyboard *keyboard)
+{
+ if (keyboard != NULL)
+ free(keyboard);
+}
+
+HangulCombination*
+hangul_combination_new()
+{
+ HangulCombination *combination = malloc(sizeof(HangulCombination));
+ if (combination != NULL) {
+ combination->size = 0;
+ combination->table = NULL;
+ return combination;
+ }
+
+ return NULL;
+}
+
+void
+hangul_combination_delete(HangulCombination *combination)
+{
+ if (combination != NULL) {
+ if (combination->table != NULL)
+ free(combination->table);
+ free(combination);
+ }
+}
+
+static uint32_t
+hangul_combination_make_key(ucschar first, ucschar second)
+{
+ return first << 16 | second;
+}
+
+bool
+hangul_combination_set_data(HangulCombination* combination,
+ ucschar* first, ucschar* second, ucschar* result,
+ unsigned int n)
+{
+ if (combination == NULL)
+ return false;
+
+ if (n == 0 || n > ULONG_MAX / sizeof(HangulCombinationItem))
+ return false;
+
+ combination->table = malloc(sizeof(HangulCombinationItem) * n);
+ if (combination->table != NULL) {
+ int i;
+
+ combination->size = n;
+ for (i = 0; i < n; i++) {
+ combination->table[i].key = hangul_combination_make_key(first[i], second[i]);
+ combination->table[i].code = result[i];
+ }
+ return true;
+ }
+
+ return false;
+}
+
+static int
+hangul_combination_cmp(const void* p1, const void* p2)
+{
+ const HangulCombinationItem *item1 = p1;
+ const HangulCombinationItem *item2 = p2;
+ return item1->key - item2->key;
+}
+
+ucschar
+hangul_combination_combine(const HangulCombination* combination,
+ ucschar first, ucschar second)
+{
+ HangulCombinationItem *res;
+ HangulCombinationItem key;
+
+ if (combination == NULL)
+ return 0;
+
+ key.key = hangul_combination_make_key(first, second);
+ res = bsearch(&key, combination->table, combination->size,
+ sizeof(combination->table[0]), hangul_combination_cmp);
+ if (res != NULL)
+ return res->code;
+
+ return 0;
+}
+
+static bool
+hangul_buffer_is_empty(HangulBuffer *buffer)
+{
+ return buffer->choseong == 0 && buffer->jungseong == 0 &&
+ buffer->jongseong == 0;
+}
+
+static bool
+hangul_buffer_has_choseong(HangulBuffer *buffer)
+{
+ return buffer->choseong != 0;
+}
+
+static bool
+hangul_buffer_has_jungseong(HangulBuffer *buffer)
+{
+ return buffer->jungseong != 0;
+}
+
+static bool
+hangul_buffer_has_jongseong(HangulBuffer *buffer)
+{
+ return buffer->jongseong != 0;
+}
+
+static void
+hangul_buffer_push(HangulBuffer *buffer, ucschar ch)
+{
+ if (hangul_is_choseong(ch)) {
+ buffer->choseong = ch;
+ } else if (hangul_is_jungseong(ch)) {
+ buffer->jungseong = ch;
+ } else if (hangul_is_jongseong(ch)) {
+ buffer->jongseong = ch;
+ } else {
+ }
+
+ buffer->stack[++buffer->index] = ch;
+}
+
+static ucschar
+hangul_buffer_pop(HangulBuffer *buffer)
+{
+ return buffer->stack[buffer->index--];
+}
+
+static ucschar
+hangul_buffer_peek(HangulBuffer *buffer)
+{
+ if (buffer->index < 0)
+ return 0;
+
+ return buffer->stack[buffer->index];
+}
+
+static void
+hangul_buffer_clear(HangulBuffer *buffer)
+{
+ buffer->choseong = 0;
+ buffer->jungseong = 0;
+ buffer->jongseong = 0;
+
+ buffer->index = -1;
+ buffer->stack[0] = 0;
+ buffer->stack[1] = 0;
+ buffer->stack[2] = 0;
+ buffer->stack[3] = 0;
+ buffer->stack[4] = 0;
+ buffer->stack[5] = 0;
+ buffer->stack[6] = 0;
+ buffer->stack[7] = 0;
+ buffer->stack[8] = 0;
+ buffer->stack[9] = 0;
+ buffer->stack[10] = 0;
+ buffer->stack[11] = 0;
+}
+
+static int
+hangul_buffer_get_jamo_string(HangulBuffer *buffer, ucschar *buf, int buflen)
+{
+ int n = 0;
+
+ if (buffer->choseong || buffer->jungseong || buffer->jongseong) {
+ if (buffer->choseong) {
+ buf[n++] = buffer->choseong;
+ } else {
+ buf[n++] = HANGUL_CHOSEONG_FILLER;
+ }
+ if (buffer->jungseong) {
+ buf[n++] = buffer->jungseong;
+ } else {
+ buf[n++] = HANGUL_JUNGSEONG_FILLER;
+ }
+ if (buffer->jongseong) {
+ buf[n++] = buffer->jongseong;
+ }
+ }
+
+ buf[n] = 0;
+
+ return n;
+}
+
+static int
+hangul_jaso_to_string(ucschar cho, ucschar jung, ucschar jong,
+ ucschar *buf, int len)
+{
+ ucschar ch = 0;
+ int n = 0;
+
+ if (cho) {
+ if (jung) {
+ /* have cho, jung, jong or no jong */
+ ch = hangul_jaso_to_syllable(cho, jung, jong);
+ buf[n++] = ch;
+ } else {
+ if (jong) {
+ /* have cho, jong */
+ ch = hangul_jaso_to_jamo(cho);
+ buf[n++] = ch;
+ ch = hangul_jaso_to_jamo(jong);
+ buf[n++] = ch;
+ } else {
+ /* have cho */
+ ch = hangul_jaso_to_jamo(cho);
+ buf[n++] = ch;
+ }
+ }
+ } else {
+ if (jung) {
+ if (jong) {
+ /* have jung, jong */
+ ch = hangul_jaso_to_jamo(jung);
+ buf[n++] = ch;
+ ch = hangul_jaso_to_jamo(jong);
+ buf[n++] = ch;
+ } else {
+ /* have jung */
+ ch = hangul_jaso_to_jamo(jung);
+ buf[n++] = ch;
+ }
+ } else {
+ if (jong) {
+ /* have jong */
+ ch = hangul_jaso_to_jamo(jong);
+ buf[n++] = ch;
+ } else {
+ /* have nothing */
+ buf[n] = 0;
+ }
+ }
+ }
+ buf[n] = 0;
+
+ return n;
+}
+
+static int
+hangul_buffer_get_string(HangulBuffer *buffer, ucschar *buf, int buflen)
+{
+ return hangul_jaso_to_string(buffer->choseong,
+ buffer->jungseong,
+ buffer->jongseong,
+ buf, buflen);
+}
+
+static bool
+hangul_buffer_backspace(HangulBuffer *buffer)
+{
+ if (buffer->index >= 0) {
+ ucschar ch = hangul_buffer_pop(buffer);
+ if (ch == 0)
+ return false;
+
+ if (hangul_is_choseong(ch)) {
+ ch = hangul_buffer_peek(buffer);
+ buffer->choseong = hangul_is_choseong(ch) ? ch : 0;
+ return true;
+ } else if (hangul_is_jungseong(ch)) {
+ ch = hangul_buffer_peek(buffer);
+ buffer->jungseong = hangul_is_jungseong(ch) ? ch : 0;
+ return true;
+ } else if (hangul_is_jongseong(ch)) {
+ ch = hangul_buffer_peek(buffer);
+ buffer->jongseong = hangul_is_jongseong(ch) ? ch : 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+static
+#ifndef __SYMBIAN32__
+inline
+#endif
+bool
+hangul_ic_push(HangulInputContext *hic, ucschar c)
+{
+ ucschar buf[64] = { 0, };
+ if (hic->on_transition != NULL) {
+ ucschar cho, jung, jong;
+ if (hangul_is_choseong(c)) {
+ cho = c;
+ jung = hic->buffer.jungseong;
+ jong = hic->buffer.jongseong;
+ } else if (hangul_is_jungseong(c)) {
+ cho = hic->buffer.choseong;
+ jung = c;
+ jong = hic->buffer.jongseong;
+ } else if (hangul_is_jongseong(c)) {
+ cho = hic->buffer.choseong;
+ jung = hic->buffer.jungseong;
+ jong = c;
+ } else {
+ hangul_ic_flush_internal(hic);
+ return false;
+ }
+
+ hangul_jaso_to_string(cho, jung, jong, buf, N_ELEMENTS(buf));
+ if (!hic->on_transition(hic, c, buf, hic->on_transition_data)) {
+ hangul_ic_flush_internal(hic);
+ return false;
+ }
+ } else {
+ if (!hangul_is_jaso(c)) {
+ hangul_ic_flush_internal(hic);
+ return false;
+ }
+ }
+
+ hangul_buffer_push(&hic->buffer, c);
+ return true;
+}
+
+static
+#ifndef __SYMBIAN32__
+inline
+#endif
+ucschar
+hangul_ic_pop(HangulInputContext *hic)
+{
+ return hangul_buffer_pop(&hic->buffer);
+}
+
+static
+#ifndef __SYMBIAN32__
+inline
+#endif
+ucschar
+hangul_ic_peek(HangulInputContext *hic)
+{
+ return hangul_buffer_peek(&hic->buffer);
+}
+
+static
+#ifndef __SYMBIAN32__
+inline
+#endif
+void
+hangul_ic_save_preedit_string(HangulInputContext *hic)
+{
+ if (hic->output_mode == HANGUL_OUTPUT_JAMO) {
+ hangul_buffer_get_jamo_string(&hic->buffer,
+ hic->preedit_string,
+ N_ELEMENTS(hic->preedit_string));
+ } else {
+ hangul_buffer_get_string(&hic->buffer,
+ hic->preedit_string,
+ N_ELEMENTS(hic->preedit_string));
+ }
+}
+
+static
+#ifndef __SYMBIAN32__
+inline
+#endif
+void
+hangul_ic_append_commit_string(HangulInputContext *hic, ucschar ch)
+{
+ int i;
+
+ for (i = 0; i < N_ELEMENTS(hic->commit_string); i++) {
+ if (hic->commit_string[i] == 0)
+ break;
+ }
+
+ if (i + 1 < N_ELEMENTS(hic->commit_string)) {
+ hic->commit_string[i++] = ch;
+ hic->commit_string[i] = 0;
+ }
+}
+
+static
+#ifndef __SYMBIAN32__
+inline
+#endif
+void
+hangul_ic_save_commit_string(HangulInputContext *hic)
+{
+ ucschar *string = hic->commit_string;
+ int len = N_ELEMENTS(hic->commit_string);
+
+ while (len > 0) {
+ if (*string == 0)
+ break;
+ len--;
+ string++;
+ }
+
+ if (hic->output_mode == HANGUL_OUTPUT_JAMO) {
+ hangul_buffer_get_jamo_string(&hic->buffer, string, len);
+ } else {
+ hangul_buffer_get_string(&hic->buffer, string, len);
+ }
+
+ hangul_buffer_clear(&hic->buffer);
+}
+
+static bool
+hangul_ic_process_jamo(HangulInputContext *hic, ucschar ch)
+{
+ ucschar jong;
+ ucschar combined;
+
+ if (!hangul_is_jaso(ch) && ch > 0) {
+ hangul_ic_save_commit_string(hic);
+ hangul_ic_append_commit_string(hic, ch);
+ return true;
+ }
+
+ if (hic->buffer.jongseong) {
+ if (hangul_is_choseong(ch)) {
+ jong = hangul_choseong_to_jongseong(ch);
+ combined = hangul_combination_combine(hic->combination,
+ hic->buffer.jongseong, jong);
+ if (hangul_is_jongseong(combined)) {
+ if (!hangul_ic_push(hic, combined)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+ hangul_ic_save_commit_string(hic);
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else if (hangul_is_jungseong(ch)) {
+ ucschar pop, peek;
+ pop = hangul_ic_pop(hic);
+ peek = hangul_ic_peek(hic);
+
+ if (hangul_is_jungseong(peek)) {
+ hic->buffer.jongseong = 0;
+ hangul_ic_save_commit_string(hic);
+ hangul_ic_push(hic, hangul_jongseong_to_choseong(pop));
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ } else {
+ ucschar choseong = 0, jongseong = 0;
+ hangul_jongseong_dicompose(hic->buffer.jongseong,
+ &jongseong, &choseong);
+ hic->buffer.jongseong = jongseong;
+ hangul_ic_save_commit_string(hic);
+ hangul_ic_push(hic, choseong);
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+ goto flush;
+ }
+ } else if (hic->buffer.jungseong) {
+ if (hangul_is_choseong(ch)) {
+ if (hic->buffer.choseong) {
+ jong = hangul_choseong_to_jongseong(ch);
+ if (hangul_is_jongseong(jong)) {
+ if (!hangul_ic_push(hic, jong)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+ hangul_ic_save_commit_string(hic);
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+#if 1
+ hangul_ic_save_commit_string(hic);
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+#else
+ if (!hangul_ic_push(hic, ch)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+#endif
+ }
+ } else if (hangul_is_jungseong(ch)) {
+ combined = hangul_combination_combine(hic->combination,
+ hic->buffer.jungseong, ch);
+ if (hangul_is_jungseong(combined)) {
+ if (!hangul_ic_push(hic, combined)) {
+ return false;
+ }
+ } else {
+ hangul_ic_save_commit_string(hic);
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+ goto flush;
+ }
+ } else if (hic->buffer.choseong) {
+ if (hangul_is_choseong(ch)) {
+ combined = hangul_combination_combine(hic->combination,
+ hic->buffer.choseong, ch);
+ if (!hangul_ic_push(hic, combined)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+ if (!hangul_ic_push(hic, ch)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ }
+ } else {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+
+ hangul_ic_save_preedit_string(hic);
+ return true;
+
+flush:
+ hangul_ic_flush_internal(hic);
+ return false;
+}
+
+static bool
+hangul_ic_process_jaso(HangulInputContext *hic, ucschar ch)
+{
+ if (hangul_is_choseong(ch)) {
+ if (hic->buffer.choseong == 0) {
+ if (!hangul_ic_push(hic, ch)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+ ucschar choseong = 0;
+ if (hangul_is_choseong(hangul_ic_peek(hic))) {
+ choseong = hangul_combination_combine(hic->combination,
+ hic->buffer.choseong, ch);
+ }
+ if (choseong) {
+ if (!hangul_ic_push(hic, choseong)) {
+ if (!hangul_ic_push(hic, choseong)) {
+ return false;
+ }
+ }
+ } else {
+ hangul_ic_save_commit_string(hic);
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ }
+ } else if (hangul_is_jungseong(ch)) {
+ if (hic->buffer.jungseong == 0) {
+ if (!hangul_ic_push(hic, ch)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+ ucschar jungseong = 0;
+ if (hangul_is_jungseong(hangul_ic_peek(hic))) {
+ jungseong = hangul_combination_combine(hic->combination,
+ hic->buffer.jungseong, ch);
+ }
+ if (jungseong) {
+ if (!hangul_ic_push(hic, jungseong)) {
+ if (!hangul_ic_push(hic, jungseong)) {
+ return false;
+ }
+ }
+ } else {
+ hangul_ic_save_commit_string(hic);
+ if (!hangul_ic_push(hic, ch)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ }
+ }
+ } else if (hangul_is_jongseong(ch)) {
+ if (hic->buffer.jongseong == 0) {
+ if (!hangul_ic_push(hic, ch)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ } else {
+ ucschar jongseong = 0;
+ if (hangul_is_jongseong(hangul_ic_peek(hic))) {
+ jongseong = hangul_combination_combine(hic->combination,
+ hic->buffer.jongseong, ch);
+ }
+ if (jongseong) {
+ if (!hangul_ic_push(hic, jongseong)) {
+ if (!hangul_ic_push(hic, jongseong)) {
+ return false;
+ }
+ }
+ } else {
+ hangul_ic_save_commit_string(hic);
+ if (!hangul_ic_push(hic, ch)) {
+ if (!hangul_ic_push(hic, ch)) {
+ return false;
+ }
+ }
+ }
+ }
+ } else if (ch > 0) {
+ hangul_ic_save_commit_string(hic);
+ hangul_ic_append_commit_string(hic, ch);
+ } else {
+ hangul_ic_save_commit_string(hic);
+ return false;
+ }
+
+ hangul_ic_save_preedit_string(hic);
+ return true;
+}
+
+bool
+hangul_ic_process(HangulInputContext *hic, int ascii)
+{
+ ucschar c;
+
+ if (hic == NULL)
+ return false;
+
+ hic->preedit_string[0] = 0;
+ hic->commit_string[0] = 0;
+
+ c = hangul_keyboard_get_value(hic->keyboard, ascii);
+ if (hic->on_translate != NULL)
+ hic->on_translate(hic, ascii, &c, hic->on_translate_data);
+
+ if (hangul_keyboard_get_type(hic->keyboard) == HANGUL_KEYBOARD_TYPE_JAMO)
+ return hangul_ic_process_jamo(hic, c);
+ else
+ return hangul_ic_process_jaso(hic, c);
+}
+
+const ucschar*
+hangul_ic_get_preedit_string(HangulInputContext *hic)
+{
+ if (hic == NULL)
+ return NULL;
+
+ return hic->preedit_string;
+}
+
+const ucschar*
+hangul_ic_get_commit_string(HangulInputContext *hic)
+{
+ if (hic == NULL)
+ return NULL;
+
+ return hic->commit_string;
+}
+
+void
+hangul_ic_reset(HangulInputContext *hic)
+{
+ if (hic == NULL)
+ return;
+
+ hic->preedit_string[0] = 0;
+ hic->commit_string[0] = 0;
+ hic->flushed_string[0] = 0;
+
+ hangul_buffer_clear(&hic->buffer);
+}
+
+/* append current preedit to the commit buffer.
+ * this function does not clear previously made commit string. */
+static void
+hangul_ic_flush_internal(HangulInputContext *hic)
+{
+ hic->preedit_string[0] = 0;
+
+ hangul_ic_save_commit_string(hic);
+ hangul_buffer_clear(&hic->buffer);
+}
+
+const ucschar*
+hangul_ic_flush(HangulInputContext *hic)
+{
+ if (hic == NULL)
+ return NULL;
+
+ // get the remaining string and clear the buffer
+ hic->preedit_string[0] = 0;
+ hic->commit_string[0] = 0;
+ hic->flushed_string[0] = 0;
+
+ if (hic->output_mode == HANGUL_OUTPUT_JAMO) {
+ hangul_buffer_get_jamo_string(&hic->buffer, hic->flushed_string,
+ N_ELEMENTS(hic->flushed_string));
+ } else {
+ hangul_buffer_get_string(&hic->buffer, hic->flushed_string,
+ N_ELEMENTS(hic->flushed_string));
+ }
+
+ hangul_buffer_clear(&hic->buffer);
+
+ return hic->flushed_string;
+}
+
+bool
+hangul_ic_backspace(HangulInputContext *hic)
+{
+ int ret;
+
+ if (hic == NULL)
+ return false;
+
+ hic->preedit_string[0] = 0;
+ hic->commit_string[0] = 0;
+
+ ret = hangul_buffer_backspace(&hic->buffer);
+ if (ret)
+ hangul_ic_save_preedit_string(hic);
+ return ret;
+}
+
+int
+hangul_ic_dvorak_to_qwerty(int qwerty)
+{
+ static const int table[] = {
+ '!', /* ! */
+ 'Q', /* " */
+ '#', /* # */
+ '$', /* $ */
+ '%', /* % */
+ '&', /* & */
+ 'q', /* ' */
+ '(', /* ( */
+ ')', /* ) */
+ '*', /* * */
+ '}', /* + */
+ 'w', /* , */
+ '\'', /* - */
+ 'e', /* . */
+ '[', /* / */
+ '0', /* 0 */
+ '1', /* 1 */
+ '2', /* 2 */
+ '3', /* 3 */
+ '4', /* 4 */
+ '5', /* 5 */
+ '6', /* 6 */
+ '7', /* 7 */
+ '8', /* 8 */
+ '9', /* 9 */
+ 'Z', /* : */
+ 'z', /* ; */
+ 'W', /* < */
+ ']', /* = */
+ 'E', /* > */
+ '{', /* ? */
+ '@', /* @ */
+ 'A', /* A */
+ 'N', /* B */
+ 'I', /* C */
+ 'H', /* D */
+ 'D', /* E */
+ 'Y', /* F */
+ 'U', /* G */
+ 'J', /* H */
+ 'G', /* I */
+ 'C', /* J */
+ 'V', /* K */
+ 'P', /* L */
+ 'M', /* M */
+ 'L', /* N */
+ 'S', /* O */
+ 'R', /* P */
+ 'X', /* Q */
+ 'O', /* R */
+ ':', /* S */
+ 'K', /* T */
+ 'F', /* U */
+ '>', /* V */
+ '<', /* W */
+ 'B', /* X */
+ 'T', /* Y */
+ '?', /* Z */
+ '-', /* [ */
+ '\\', /* \ */
+ '=', /* ] */
+ '^', /* ^ */
+ '"', /* _ */
+ '`', /* ` */
+ 'a', /* a */
+ 'n', /* b */
+ 'i', /* c */
+ 'h', /* d */
+ 'd', /* e */
+ 'y', /* f */
+ 'u', /* g */
+ 'j', /* h */
+ 'g', /* i */
+ 'c', /* j */
+ 'v', /* k */
+ 'p', /* l */
+ 'm', /* m */
+ 'l', /* n */
+ 's', /* o */
+ 'r', /* p */
+ 'x', /* q */
+ 'o', /* r */
+ ';', /* s */
+ 'k', /* t */
+ 'f', /* u */
+ '.', /* v */
+ ',', /* w */
+ 'b', /* x */
+ 't', /* y */
+ '/', /* z */
+ '_', /* { */
+ '|', /* | */
+ '+', /* } */
+ '~' /* ~ */
+ };
+
+ if (qwerty >= '!' && qwerty <= '~')
+ return table[qwerty - '!'];
+
+ return qwerty;
+}
+
+bool
+hangul_ic_is_empty(HangulInputContext *hic)
+{
+ return hangul_buffer_is_empty(&hic->buffer);
+}
+
+bool
+hangul_ic_has_choseong(HangulInputContext *hic)
+{
+ return hangul_buffer_has_choseong(&hic->buffer);
+}
+
+bool
+hangul_ic_has_jungseong(HangulInputContext *hic)
+{
+ return hangul_buffer_has_jungseong(&hic->buffer);
+}
+
+bool
+hangul_ic_has_jongseong(HangulInputContext *hic)
+{
+ return hangul_buffer_has_jongseong(&hic->buffer);
+}
+
+void
+hangul_ic_set_output_mode(HangulInputContext *hic, int mode)
+{
+ if (hic == NULL)
+ return;
+
+ if (!hic->use_jamo_mode_only)
+ hic->output_mode = mode;
+}
+
+void
+hangul_ic_connect_translate (HangulInputContext* hic,
+ HangulOnTranslate callback,
+ void* user_data)
+{
+ if (hic != NULL) {
+ hic->on_translate = callback;
+ hic->on_translate_data = user_data;
+ }
+}
+
+void
+hangul_ic_connect_transition(HangulInputContext* hic,
+ HangulOnTransition callback,
+ void* user_data)
+{
+ if (hic != NULL) {
+ hic->on_transition = callback;
+ hic->on_transition_data = user_data;
+ }
+}
+
+void hangul_ic_connect_callback(HangulInputContext* hic, const char* event,
+ void* callback, void* user_data)
+{
+ if (hic == NULL || event == NULL)
+ return;
+
+ if (strcasecmp(event, "translate") == 0) {
+ hic->on_translate = (HangulOnTranslate)callback;
+ hic->on_translate_data = user_data;
+ } else if (strcasecmp(event, "transition") == 0) {
+ hic->on_transition = (HangulOnTransition)callback;
+ hic->on_transition_data = user_data;
+ }
+}
+
+void hangul_ic_set_filter(HangulInputContext *hic,
+ HangulICFilter func, void *user_data)
+{
+ return;
+}
+
+void
+hangul_ic_set_keyboard(HangulInputContext *hic, const HangulKeyboard* keyboard)
+{
+ if (hic == NULL || keyboard == NULL)
+ return;
+
+ hic->keyboard = keyboard;
+}
+
+void
+hangul_ic_select_keyboard(HangulInputContext *hic, const char* id)
+{
+ if (hic == NULL)
+ return;
+
+ if (id == NULL)
+ id = "2";
+
+ if (strcmp(id, "32") == 0) {
+ hic->keyboard = &hangul_keyboard_32;
+ hic->combination = &hangul_combination_default;
+ hic->output_mode = HANGUL_OUTPUT_SYLLABLE;
+ hic->use_jamo_mode_only = FALSE;
+ } else if (strcmp(id, "39") == 0) {
+ hic->keyboard = &hangul_keyboard_390;
+ hic->combination = &hangul_combination_default;
+ hic->output_mode = HANGUL_OUTPUT_SYLLABLE;
+ hic->use_jamo_mode_only = FALSE;
+ } else if (strcmp(id, "3f") == 0) {
+ hic->keyboard = &hangul_keyboard_3final;
+ hic->combination = &hangul_combination_default;
+ hic->output_mode = HANGUL_OUTPUT_SYLLABLE;
+ hic->use_jamo_mode_only = FALSE;
+ } else if (strcmp(id, "3s") == 0) {
+ hic->keyboard = &hangul_keyboard_3sun;
+ hic->combination = &hangul_combination_default;
+ hic->output_mode = HANGUL_OUTPUT_SYLLABLE;
+ hic->use_jamo_mode_only = FALSE;
+ } else if (strcmp(id, "3y") == 0) {
+ hic->keyboard = &hangul_keyboard_3yet;
+ hic->combination = &hangul_combination_full;
+ hic->output_mode = HANGUL_OUTPUT_JAMO;
+ hic->use_jamo_mode_only = TRUE;
+ } else {
+ hic->keyboard = &hangul_keyboard_2;
+ hic->combination = &hangul_combination_default;
+ hic->output_mode = HANGUL_OUTPUT_SYLLABLE;
+ hic->use_jamo_mode_only = FALSE;
+ }
+}
+
+void
+hangul_ic_set_combination(HangulInputContext *hic,
+ const HangulCombination* combination)
+{
+ if (hic == NULL || combination == NULL)
+ return;
+
+ hic->combination = combination;
+}
+
+HangulInputContext*
+hangul_ic_new(const char* keyboard)
+{
+ HangulInputContext *hic;
+
+ int size=sizeof(HangulInputContext);
+
+ hic = malloc(size);
+ if (hic == NULL)
+ return NULL;
+
+ hic->preedit_string[0] = 0;
+ hic->commit_string[0] = 0;
+ hic->flushed_string[0] = 0;
+
+ hic->on_translate = NULL;
+ hic->on_translate_data = NULL;
+
+ hic->on_transition = NULL;
+ hic->on_transition_data = NULL;
+
+ hic->use_jamo_mode_only = FALSE;
+
+ hangul_ic_set_output_mode(hic, HANGUL_OUTPUT_SYLLABLE);
+ hangul_ic_select_keyboard(hic, keyboard);
+
+ hangul_buffer_clear(&hic->buffer);
+
+ return hic;
+}
+
+void
+hangul_ic_delete(HangulInputContext *hic)
+{
+ if (hic == NULL)
+ return;
+
+ free(hic);
+}