/* 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);
}