textinput/ptihangulcore/src/hangulinputcontext.c
branchRCL_3
changeset 7 6defe5d1bd39
parent 6 6ceef9a83b1a
child 8 4eb1ae11334f
--- a/textinput/ptihangulcore/src/hangulinputcontext.c	Mon Mar 15 12:42:02 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1232 +0,0 @@
-/* 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);
-}