static ucschar
hangul_ic_combine(HangulInputContext* hic, ucschar first, ucschar second)
{
    if (!hic->option_combi_on_double_stroke) {
	if (hangul_keyboard_get_type(hic->keyboard) == HANGUL_KEYBOARD_TYPE_JAMO) {
	    /* 옛한글은 아래 규칙을 적용하지 않아야 입력가능한 글자가 있으므로
	     * 적용하지 않는다. */
	    if (first == second &&
		hangul_is_jamo_conjoinable(first)) {
		return 0;
	    }
	}
    }

    ucschar combined = 0;
    combined = hangul_keyboard_combine(hic->keyboard, 0, first, second);

    if (!hic->option_non_choseong_combi) {
	if (hangul_is_choseong(first) && hangul_is_choseong(second) &&
	    hangul_is_jongseong(combined)) {
	    return 0;
	}
    }

    return combined;
}
/**
 * @ingroup hangulic
 * @brief 키 입력을 처리하여 실제로 한글 조합을 하는 함수
 * @param hic @ref HangulInputContext 오브젝트
 * @param ascii 키 이벤트
 * @return @ref HangulInputContext 가 이 키를 사용했으면 true,
 *	     사용하지 않았으면 false
 *
 * ascii 값으로 주어진 키 이벤트를 받아서 내부의 한글 조합 상태를
 * 변화시키고, preedit, commit 스트링을 저장한다.
 *
 * libhangul의 키 이벤트 프로세스는 ASCII 코드 값을 기준으로 처리한다.
 * 이 키 값은 US Qwerty 자판 배열에서의 키 값에 해당한다.
 * 따라서 유럽어 자판을 사용하는 경우에는 해당 키의 ASCII 코드를 직접
 * 전달하면 안되고, 그 키가 US Qwerty 자판이었을 경우에 발생할 수 있는 
 * ASCII 코드 값을 주어야 한다.
 * 또한 ASCII 코드 이므로 Shift 상태는 대문자로 전달이 된다.
 * Capslock이 눌린 경우에는 대소문자를 뒤바꾸어 보내주지 않으면 
 * 마치 Shift가 눌린 것 처럼 동작할 수 있으므로 주의한다.
 * preedit, commit 스트링은 hangul_ic_get_preedit_string(),
 * hangul_ic_get_commit_string() 함수를 이용하여 구할 수 있다.
 * 
 * 이 함수의 사용법에 대한 설명은 @ref hangulicusage 부분을 참조한다.
 *
 * @remarks 이 함수는 @ref HangulInputContext 의 상태를 변화 시킨다.
 */
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_mapping(hic->keyboard, 0, ascii);
    if (hic->on_translate != NULL)
	hic->on_translate(hic, ascii, &c, hic->on_translate_data);

    if (ascii == '\b') {
	return hangul_ic_backspace(hic);
    }

    int type = hangul_keyboard_get_type(hic->keyboard);
    switch (type) {
    case HANGUL_KEYBOARD_TYPE_JASO:
    case HANGUL_KEYBOARD_TYPE_JASO_YET:
	return hangul_ic_process_jaso(hic, c);
    case HANGUL_KEYBOARD_TYPE_ROMAJA:
	return hangul_ic_process_romaja(hic, ascii, c);
    default:
	return hangul_ic_process_jamo(hic, c);
    }
}
/**
 * @ingroup hangulic
 * @brief 키 입력을 처리하여 실제로 한글 조합을 하는 함수
 * @param hic @ref HangulInputContext 오브젝트
 * @param ascii 키 이벤트
 * @return @ref HangulInputContext가 이 키를 사용했으면 true,
 *	     사용하지 않았으면 false
 *
 * ascii 값으로 주어진 키 이벤트를 받아서 내부의 한글 조합 상태를
 * 변화시키고, preedit, commit 스트링을 저장한다.
 *
 * libhangul의 키 이벤트 프로세스는 ASCII 코드 값을 기준으로 처리한다.
 * 이 키 값은 US Qwerty 자판 배열에서의 키 값에 해당한다.
 * 따라서 유럽어 자판을 사용하는 경우에는 해당 키의 ASCII 코드를 직접
 * 전달하면 안되고, 그 키가 US Qwerty 자판이었을 경우에 발생할 수 있는 
 * ASCII 코드 값을 주어야 한다.
 * 또한 ASCII 코드 이므로 Shift 상태는 대문자로 전달이 된다.
 * Capslock이 눌린 경우에는 대소문자를 뒤바꾸어 보내주지 않으면 
 * 마치 Shift가 눌린 것 처럼 동작할 수 있으므로 주의한다.
 * preedit, commit 스트링은 hangul_ic_get_preedit_string(),
 * hangul_ic_get_commit_string() 함수를 이용하여 구할 수 있다.
 * 
 * 이 함수의 사용법에 대한 설명은 @ref hangulicusage 부분을 참조한다.
 *
 * @remarks 이 함수는 @ref HangulInputContext의 상태를 변화 시킨다.
 */
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 if (hangul_keyboard_get_type(hic->keyboard) == HANGUL_KEYBOARD_TYPE_JASO)
	return hangul_ic_process_jaso(hic, c);
    else
	return hangul_ic_process_romaja(hic, ascii, c);
}
/**
 * @ingroup hangulic
 * @brief 주어진 hic가 transliteration method인지 판별
 * @param hic 상태를 알고자 하는 HangulInputContext 포인터
 * @return hic가 transliteration method인 경우 true를 리턴, 아니면 false
 *
 * 이 함수는 @a hic 가 transliteration method인지 판별하는 함수다.
 * 이 함수가 false를 리턴할 경우에는 process 함수에 keycode를 넘기기 전에
 * 키보드 자판 배열에 독립적인 값으로 변환한 후 넘겨야 한다.
 * 그렇지 않으면 유럽어 자판과 한국어 자판을 같이 쓸때 한글 입력이 제대로
 * 되지 않는다.
 */
bool
hangul_ic_is_transliteration(HangulInputContext *hic)
{
    int type;

    if (hic == NULL)
	return false;

    type = hangul_keyboard_get_type(hic->keyboard);
    if (type == HANGUL_KEYBOARD_TYPE_ROMAJA)
	return true;

    return false;
}
static ucschar
hangul_ic_choseong_to_jongseong(HangulInputContext* hic, ucschar cho)
{
    ucschar jong = hangul_choseong_to_jongseong(cho);
    if (hangul_is_jongseong_conjoinable(jong)) {
	return jong;
    } else {
	/* 옛글 조합 규칙을 사용하는 자판의 경우에는 종성이 conjoinable
	 * 하지 않아도 상관없다 */
	int type = hangul_keyboard_get_type(hic->keyboard);
	switch (type) {
	case HANGUL_KEYBOARD_TYPE_JAMO_YET:
	case HANGUL_KEYBOARD_TYPE_JASO_YET:
	    return jong;
	}
    }

    return 0;
}