diff -r eb1f2e154e89 -r f5a1e66df979 textinput/ptihangulcore/src/hangulinputcontext.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textinput/ptihangulcore/src/hangulinputcontext.c Fri Feb 19 23:09:27 2010 +0200 @@ -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 +#endif + +#include +#include +#include +#include +#include + +#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); +}