/*
  IIIMPEIMIL.c
   utilities to interexchange between EIMIL and IIIMP.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <EIMIL.h>
#include <iiimp.h>

#define EIMIL_IIIMP_INIT_BUFFER_SIZE 32

static int
set_feedback_prop(
    EIMIL_mtext *pm,
    int val,
    int st,
    int end
)
{
    EIMIL_value *pv_idx, *pv_val, *pv_prop;

    pv_idx = EIMIL_construct_number(0);
    if (!pv_idx) return 0;
    pv_val = EIMIL_construct_number(val);
    if (!pv_val) {
	EIMIL_RMREF(*pv_idx);
	return 0;
    }
    pv_prop = EIMIL_construct_prop(pEIMIL_feedback_sym);
    if (!pv_prop) {
	EIMIL_RMREF(*pv_idx);
	EIMIL_RMREF(*pv_val);
	return 0;
    }
    if ((!EIMIL_add_prop(&pv_prop->v.prop, pv_idx))
	|| (!EIMIL_add_prop(&pv_prop->v.prop, pv_val))
	|| (!EIMIL_set_prop_on_mtext(pm, pv_prop, st, end))) {
	EIMIL_RMREF(*pv_idx);
	EIMIL_RMREF(*pv_val);
	EIMIL_RMREF(*pv_prop);
	return 0;
    }

    return 1;
}

EIMIL_value*
EIMIL_construct_mtext_from_iiimp_text(
    IIIMP_text *pimt
)
{
    int i, idx;
    EIMIL_value *pv_mtext;
    EIMIL_mtext *pm;
    {
	int cur_fid0_val, cur_fid0_st;
	int len;
	int buflen = EIMIL_IIIMP_INIT_BUFFER_SIZE;
	UTF16 *pstrh, *pstr;
	IIIMP_char_with_feedback *pcwf;
	IIIMP_feedback_attr_list *pfal;
	IIIMP_feedback_attr *pfa;

	len = 0;
	pstrh = pstr = (UTF16*) malloc(buflen * sizeof(UTF16));
	if (!pstrh) return NULL;

	/* string */
	for (pcwf = pimt->char_with_feedback;
	     pcwf; pcwf = pcwf->next) {
	    if (len >= buflen) {
		buflen *= 2;
		pstr = (UTF16*) realloc(pstrh, buflen * sizeof(UTF16));
		if (!pstr) {
		    free(pstrh);
		    return NULL;
		}
		pstrh = pstr;
		pstr += len;
	    }
	    *pstr++ = pcwf->code;
	    len++;
	}
	pv_mtext = EIMIL_construct_mtext_from_UTF16(len, pstrh);
	if (!pv_mtext) return NULL;
	free(pstrh);
	pm = &pv_mtext->v.mtext;

	/* feedback */
	cur_fid0_val = 0;
	cur_fid0_st = 0;
	idx = 0;
	for (pcwf = pimt->char_with_feedback;
	     pcwf; pcwf = pcwf->next, idx++) {
	    pfal = pcwf->feedback_attr;
	    pfa = pfal->ptr;
	    for (i = 0; i < pfal->count; i++) {
		if (pfa->id == 0) {
		    if (cur_fid0_val != pfa->feedback) {
			if (cur_fid0_val != 0) {
			    if (!set_feedback_prop(pm, cur_fid0_val, cur_fid0_st, idx))
				return NULL;
			}
			cur_fid0_st = idx;
			cur_fid0_val = pfa->feedback;
		    }
		    break;
		}
	    }
	}
	if (cur_fid0_val != 0) {
	    if (!set_feedback_prop(pm, cur_fid0_val, cur_fid0_st, idx))
		return NULL;
	}
    }
    /* TOOD: annotation!!! */

    return pv_mtext;
}

EIMIL_value*
EIMIL_construct_mtext_from_iiimp_string(
    IIIMP_string *pstr
)
{
    return EIMIL_construct_mtext_from_UTF16(pstr->len,
					    pstr->ptr);
}

EIMIL_value*
EIMIL_construct_mtext_from_iiimp_contents(
    IIIMP_contents *pimc
)
{
    if (pimc->type == IIIMP_CONTENTS_TEXT) {
	return EIMIL_construct_mtext_from_iiimp_text(pimc->value.text);
    } else if (pimc->type == IIIMP_CONTENTS_STRING) {
	return EIMIL_construct_mtext_from_iiimp_string(pimc->value.string);
    }

    return NULL;
}

int
EIMIL_update_mtext_by_preedit_draw_message(
    EIMIL_value *pbase,
    IIIMP_message *pmes,
    EIMIL_value **ppv_result
)
{
    EIMIL_mtext *pm;
    ASSERT(pbase->type == EIMIL_TYPE_MTEXT);
    pm = &pbase->v.mtext;

    if (pmes->opcode == IM_PREEDIT_DRAW) {
	int i, n = 0;
	EIMIL_value *pvs[3];
	IIIMP_preedit_draw_v *pimd = &pmes->v.preedit_draw;
	int st, end;

	st = pimd->change_first;
	end = st + pimd->change_length;

	if (st > 0) {
	    pvs[n++] = EIMIL_mtext_substr(pbase, 0, st);
	}
	if (pimd->preedit) {
	    pvs[n++] = EIMIL_construct_mtext_from_iiimp_contents(pimd->preedit);
	}
	if (end < pm->len) {
	    pvs[n++] = EIMIL_mtext_substr(pbase, end, pm->len);
	}

	if (n > 0) {
	    *ppv_result = EIMIL_mtext_concat(n, pvs);
	} else {
	    *ppv_result = NULL;
	}
	for (i = 0; i < n; i++) {
	    EIMIL_RMREF(*pvs[i]);
	}
    } else {
	return 0;
    }

    return 1;
}

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
