/*
  text.c
*/
#include <stdlib.h>
#include <string.h>
#include "iiimcfint.h"

static IIIMF_status
update_text(
    IIIMCF_text_rec *pt
)
{
    EIMIL_mtext *pm;
    if (pt->pu16) free(pt->pu16);
    if (pt->pv_mtext) {
	pm = &pt->pv_mtext->v.mtext;
	if (!EIMIL_convert_UTF32_to_UTF16(pm->ustr, pm->len, &pt->pu16, &pt->len)) {
	    return IIIMF_STATUS_MALLOC;
	}
    } else {
	pt->pu16 = NULL;
	pt->len = 0;
    }
    pt->updated = 1;

    return IIIMF_STATUS_SUCCESS;
}
#define UPDATE_TEXT(pt) (((pt)->updated) ? IIIMF_STATUS_SUCCESS : update_text(pt))

IIIMF_status
iiimcf_get_text_utf16string(
    IIIMCF_text text,
    const IIIMP_card16** putf16str
)
{
    IIIMF_status st;
    IIIMCF_text_rec *pt = (IIIMCF_text_rec*) text;

    st = UPDATE_TEXT(pt);
    if (st != IIIMF_STATUS_SUCCESS) return st;

    *putf16str = pt->pu16;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_text_length(
    IIIMCF_text text,
    int *plen
)
{
    IIIMF_status st;
    IIIMCF_text_rec *pt = (IIIMCF_text_rec*) text;

    st = UPDATE_TEXT(pt);
    if (st != IIIMF_STATUS_SUCCESS) return st;

    *plen = pt->len;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_get_char_with_feedback(
    IIIMCF_text text,
    int pos,
    IIIMP_card16 *pch,
    int *pnum_feedbacks,
    const IIIMP_card32** pfeedback_id,
    const IIIMP_card32** pfeedback
)
{
    int npos;
    IIIMCF_text_rec *pt = (IIIMCF_text_rec*) text;
    EIMIL_mtext *pm = &pt->pv_mtext->v.mtext;
    EIMIL_value *pv;

    UPDATE_TEXT(pt);
    if ((pos < 0) || (pos >= pt->len)) return IIIMF_STATUS_FAIL;
    *pch = pt->pu16[pos];

    npos = EIMIL_adjust_UTF16_pos_to_UTF32(pos, pm->ustr,
					   pm->ustr + pm->len);
    if (npos < 0) return IIIMF_STATUS_FAIL;

    *pfeedback_id = pt->pfeedback_ids;
    *pfeedback = pt->pfeedbacks;
    pv = EIMIL_get_prop_from_mtext(pm, pEIMIL_feedback_sym, npos);
    if (pv && (pv->v.prop.size > 0)) {
	int i, j, n;
	EIMIL_value **ppv = pv->v.prop.pvals;

	ASSERT(pv->type == EIMIL_TYPE_PROP);
	n = pv->v.prop.size / 2;
	if (n > IIIMCF_MAX_FEEDBACK_NUM) n = IIIMCF_MAX_FEEDBACK_NUM;
	for (i = 0, j = 0; i < n; ) {
	    pv = ppv[j++];
	    if (pv->type != EIMIL_TYPE_NUMBER) return IIIMF_STATUS_FAIL;
	    pt->pfeedback_ids[i] = pv->v.number;
	    pv = ppv[j++];
	    if (pv->type != EIMIL_TYPE_NUMBER) return IIIMF_STATUS_FAIL;
	    pt->pfeedbacks[i] = pv->v.number;
	    i++;
	}
	*pnum_feedbacks = n;
    } else {
	*pnum_feedbacks = 0;
    }

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_destruct_text(
    IIIMCF_text_rec *pt
)
{
    if (pt->pu16) free(pt->pu16);
    if (pt->pv_mtext) EIMIL_destruct_value(pt->pv_mtext);
    memset(pt, 0, sizeof(*pt));

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_duplicate_text(
    IIIMCF_text src,
    IIIMCF_text *pduplicated
)
{
    IIIMCF_text_rec *ptdup;
    IIIMCF_text_rec *pt = (IIIMCF_text_rec*) src;

    ptdup = (IIIMCF_text_rec*) malloc(sizeof(*ptdup));
    if (!ptdup) return IIIMF_STATUS_MALLOC;
    memset(ptdup, 0, sizeof(*ptdup));
    ptdup->pv_mtext = EIMIL_copy_value(pt->pv_mtext);
    if (!ptdup->pv_mtext) {
	free(ptdup);
	return IIIMF_STATUS_MALLOC;
    }

    *pduplicated = ptdup;
    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_destroy_text(
    IIIMCF_text text
)
{
    IIIMF_status st;
    IIIMCF_text_rec *pt = (IIIMCF_text_rec*) text;

    st = iiimcf_destruct_text(pt);
    free(pt);
    return st;
}

/********************************************************************************
	  convert between IIIMP_string/text/contents and IIIMCF_text
 ********************************************************************************/

IIIMF_status
iiimcf_construct_text_from_UTF8(
    const unsigned char *pstr,
    IIIMCF_text_rec *pt
)
{
    EIMIL_value *pv_mtext;

    if (pt->pv_mtext) EIMIL_destruct_value(pt->pv_mtext);
    pt->pv_mtext = NULL;
    pt->updated = 0;
    if (!pstr) {
	pt->pv_mtext = NULL;
	return IIIMF_STATUS_SUCCESS;
    }
    pv_mtext = EIMIL_construct_mtext_from_UTF8(pstr);
    if (!pv_mtext) {
	return IIIMF_STATUS_MALLOC;
    }
    pt->pv_mtext = pv_mtext;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_convert_iiimp_string_to_text(
    IIIMP_string *pstr,
    IIIMCF_text_rec *pt
)
{
    EIMIL_value *pv_mtext;

    if (pt->pv_mtext) EIMIL_destruct_value(pt->pv_mtext);
    pt->pv_mtext = NULL;
    pt->updated = 0;
    if (pstr->len == 0) {
	pt->pv_mtext = NULL;
	return IIIMF_STATUS_SUCCESS;
    }
    pv_mtext = EIMIL_construct_mtext_from_iiimp_string(pstr);
    if (!pv_mtext) {
	return IIIMF_STATUS_MALLOC;
    }
    pt->pv_mtext = pv_mtext;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_convert_iiimp_text_to_text(
    IIIMP_text *ptext,
    IIIMCF_text_rec *pt
)
{
    EIMIL_value *pv_mtext;

    if (ptext == NULL)
      return IIIMF_STATUS_FAIL;
    if (pt->pv_mtext) EIMIL_destruct_value(pt->pv_mtext);
    pt->pv_mtext = NULL;
    pt->updated = 0;
    if (!ptext->char_with_feedback) {
	pt->pv_mtext = NULL;
	return IIIMF_STATUS_SUCCESS;
    }
    pv_mtext = EIMIL_construct_mtext_from_iiimp_text(ptext);
    if (!pv_mtext) {
	return IIIMF_STATUS_MALLOC;
    }
    pt->pv_mtext = pv_mtext;

    return IIIMF_STATUS_SUCCESS;
}


IIIMF_status
iiimcf_convert_iiimp_contents_to_text(
    IIIMP_contents *pcon,
    IIIMCF_text_rec *pt
)
{
    if (pcon->type == IIIMP_CONTENTS_TEXT) {
	return iiimcf_convert_iiimp_text_to_text(pcon->value.text, pt);
    } else if (pcon->type == IIIMP_CONTENTS_STRING) {
	return iiimcf_convert_iiimp_string_to_text(pcon->value.string, pt);
    } else {
	return IIIMF_STATUS_ARGUMENT;
    }

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_update_text_by_preedit_draw(
    IIIMCF_text_rec *pbase,
    IIIMP_message *pmes
)
{
    if (!pbase->pv_mtext) {
	return iiimcf_convert_iiimp_contents_to_text(pmes->v.preedit_draw.preedit, pbase);
    } else {
	EIMIL_value *pv;

	if (!EIMIL_update_mtext_by_preedit_draw_message(pbase->pv_mtext, pmes, &pv)) {
	    iiimcf_destruct_text(pbase);
	    return IIIMF_STATUS_MALLOC;
	}
	EIMIL_destruct_value(pbase->pv_mtext);
	pbase->pv_mtext = pv;
	pbase->updated = 0;
    }
    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_append_contents_to_text(
    IIIMCF_text_rec *pbase,
    IIIMP_contents *pcon
)
{
    if (!pbase->pv_mtext) {
	return iiimcf_convert_iiimp_contents_to_text(pcon, pbase);
    } else {
	EIMIL_value *pvs[2];
	EIMIL_value *pv;

	pvs[0] = pbase->pv_mtext;
	pvs[1] = EIMIL_construct_mtext_from_iiimp_contents(pcon);
	if (!pvs[1]) return IIIMF_STATUS_MALLOC;
	pv = EIMIL_mtext_concat(2, pvs);
	if (!pv) {
	    EIMIL_destruct_value(pvs[1]);
	    return IIIMF_STATUS_MALLOC;
	}
	EIMIL_destruct_value(pbase->pv_mtext);
	pbase->pv_mtext = pv;
	pbase->updated = 0;
    }

    return IIIMF_STATUS_SUCCESS;
}

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

