#include <stdio.h>

#include "le_desktop.h"
#include "imbean.h"

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

extern LeInfoRec *le_info;

/****************************************************************************/
/*                         Ime Properties Utilities                         */
/****************************************************************************/
ImePropertyListRec* ime_property_list_duplicate(ImePropertyListRec* pl)
{
    int i;
    ImePropertyListRec *pl_dup = NULL;

    if (pl == NULL ||
        pl->count <= 0 ||
        pl->properties == NULL)
	return (NULL);

    pl_dup = (ImePropertyListRec *)calloc(1, sizeof(ImePropertyListRec));

    pl_dup->count = pl->count;
    pl_dup->properties = (ImePropertyRec *)calloc(pl_dup->count,
						  sizeof(ImePropertyRec));

    for (i = 0; i < pl_dup->count; i++) {
	ImePropertyRec *pi_dup = &(pl_dup->properties[i]);
	ImePropertyRec *pi = &(pl->properties[i]);

	pi_dup->id     = pi->id;
	pi_dup->encode = pi->encode;
	pi_dup->key    = pi->key;
	pi_dup->name   = pi->name;
	pi_dup->tip    = pi->tip;
	pi_dup->type   = pi->type;
	pi_dup->range  = pi->range;
	pi_dup->value  = pi->value;
    }

    return (pl_dup);
}

void ime_property_list_free_duplicated(ImePropertyListRec* pl)
{
    if (pl == NULL)
	return;

    if (pl->properties)
	free ((char *)pl->properties);

    free ((char *)pl);

    return;
}

/****************************************************************************/
/*                         LE Desktop Context                               */
/****************************************************************************/
LeDesktopContextRec *le_desktop_context_new()
{
    int i, num_ime_modules;
    LeDesktopContextRec *le_desktop_context = NULL;

    le_desktop_context =
	(LeDesktopContextRec *) calloc(1, sizeof(LeDesktopContextRec));
    if (le_desktop_context == NULL)
	return (NULL);

    le_desktop_context->locale = NULL;

    le_desktop_context->default_ime_module = NULL;
    le_desktop_context->default_qjbj_status = QJBJ_HALFWIDTH;
    le_desktop_context->default_punct_status = PUNCT_CHINESE;
    le_desktop_context->default_conversion_status = 0;

    le_desktop_context->num_aux_modules = 0;
    le_desktop_context->aux_modules = NULL;

    le_desktop_context->current_session = NULL;

    le_desktop_context->num_ime_modules = 0;
    le_desktop_context->ime_modules = NULL;

    if (le_info == NULL ||
        le_info->ime_modules == NULL ||
        le_info->num_ime_modules <= 0)
	return (le_desktop_context);

    le_desktop_context->ime_modules =
        (ImeModuleContextRec **) calloc(le_info->num_ime_modules,
					sizeof(ImeModuleContextRec *));
    if (le_desktop_context->ime_modules == NULL)
	return (le_desktop_context);

    num_ime_modules = 0;
    for (i = 0; i < le_info->num_ime_modules; i++) {
	ImeModuleContextRec *ime_module_context;

	if (le_info->ime_modules[i] == NULL ||
            le_info->ime_modules[i]->ime_module == NULL)
            continue;

        ime_module_context =
	    (ImeModuleContextRec *) calloc(1, sizeof(ImeModuleContextRec));
        if (ime_module_context == NULL)
            continue;

        ime_module_context->ime_module = le_info->ime_modules[i]->ime_module;
        ime_module_context->enabled = le_info->ime_modules[i]->enabled;
        ime_module_context->pl = (ImePropertyListRec *)
	    ime_property_list_duplicate(ime_module_context->ime_module->info->pl);
	
        le_desktop_context->ime_modules[num_ime_modules] = ime_module_context;
        num_ime_modules ++;
    }

    le_desktop_context->num_ime_modules = num_ime_modules;

    if (num_ime_modules > 0) 
        le_desktop_context->default_ime_module =
            le_desktop_context->ime_modules[0]->ime_module;

    le_desktop_context->time_stamp = 0;
    le_desktop_context->shortcutkey_vkb = 'K';

    return (le_desktop_context);
}

LeResult le_desktop_context_destroy(LeDesktopContextRec *le_desktop_context)
{
    int i;

    if (le_desktop_context == NULL)
	return (LE_FAIL);

    if (le_desktop_context->ime_modules != NULL) {
	for (i = 0; i < le_desktop_context->num_ime_modules; i ++) {
	    ImeModuleContextRec *ime_module_context;
	    ime_module_context = le_desktop_context->ime_modules[i];
	    if (ime_module_context == NULL)
		continue;

	    /* free property data */
	    ime_property_list_free_duplicated(ime_module_context->pl);

	    free((char *)ime_module_context);
	}       
	free((char *) le_desktop_context->ime_modules);
    }

    if (le_desktop_context->aux_modules)
	free((char *) le_desktop_context->aux_modules);

    if (le_desktop_context->locale)
	free((char *) le_desktop_context->locale);

    free((char *) le_desktop_context);

    return (LE_OK);
}

LeResult le_desktop_context_print(LeDesktopContextRec * le_desktop_context)
{
    int i;

    DEBUG_printf("le_desktop_context_print ==========\n");

    if (le_desktop_context == NULL)
	return (LE_FAIL);

    if (le_desktop_context->ime_modules != NULL) {
	for (i = 0; i < le_desktop_context->num_ime_modules; i ++) {
	    ImeModuleContextRec *ime_module_context;
	    ime_module_context = le_desktop_context->ime_modules[i];
	    if (ime_module_context == NULL)
		continue;

	    ime_module_context_print(ime_module_context);
	}       
    }

    return (LE_OK);
}

LeResult le_desktop_context_set_current_session(LeDesktopContextRec *
						le_desktop_context,
						iml_session_t * s)
{
    if (le_desktop_context == NULL)
	return (LE_FAIL);

    le_desktop_context->current_session = s;
    return (LE_OK);
}

iml_session_t *le_desktop_context_get_current_session(LeDesktopContextRec *
						      le_desktop_context)
{
    if (le_desktop_context == NULL)
	return (NULL);

    return (le_desktop_context->current_session);
}

ImeModuleRec *le_desktop_context_get_default_ime_module(LeDesktopContextRec *
							le_desktop_context)
{
    if (le_desktop_context == NULL)
	return (NULL);

    return (le_desktop_context->default_ime_module);
}

LeResult le_desktop_context_set_default_qjbj_status(LeDesktopContextRec *
						    le_desktop_context,
						    QjBjStatus
						    default_qjbj_status)
{
    if (le_desktop_context == NULL)
	return (LE_FAIL);

    le_desktop_context->default_qjbj_status = default_qjbj_status;
    return (LE_OK);
}

QjBjStatus le_desktop_context_get_default_qjbj_status(LeDesktopContextRec *
						      le_desktop_context)
{
    if (le_desktop_context == NULL)
	return (0);

    return (le_desktop_context->default_qjbj_status);
}

LeResult le_desktop_context_set_default_punct_status(LeDesktopContextRec *
						     le_desktop_context,
						     PunctStatus
						     default_punct_status)
{
    if (le_desktop_context == NULL)
	return (LE_FAIL);

    le_desktop_context->default_punct_status = default_punct_status;
    return (LE_OK);
}

PunctStatus le_desktop_context_get_default_punct_status(LeDesktopContextRec *
							le_desktop_context)
{
    if (le_desktop_context == NULL)
	return (0);

    return (le_desktop_context->default_punct_status);
}

LeResult
le_desktop_context_set_default_conversion_status(LeDesktopContextRec *
						 le_desktop_context,
						 int
						 default_conversion_status)
{
    if (le_desktop_context == NULL)
	return (LE_FAIL);

    le_desktop_context->default_conversion_status =
	default_conversion_status;
    return (LE_OK);
}

PunctStatus
le_desktop_context_get_default_conversion_status(LeDesktopContextRec *
						 le_desktop_context)
{
    if (le_desktop_context == NULL)
	return (0);

    return (le_desktop_context->default_conversion_status);
}

LeResult le_desktop_context_set_locale(LeDesktopContextRec *
				       le_desktop_context, char *locale)
{
    if (le_desktop_context == NULL || locale == NULL)
	return (LE_FAIL);

    if (le_desktop_context->locale)
	free ((char *)le_desktop_context->locale);

    le_desktop_context->locale = (char *) strdup(locale);
    return (LE_OK);
}

char *le_desktop_context_get_locale(LeDesktopContextRec *
				    le_desktop_context)
{
    if (le_desktop_context == NULL)
	return (NULL);

    return (le_desktop_context->locale);
}

/****************************************************************************/
/*                         LE Desktop Profile                               */
/****************************************************************************/
int le_desktop_profile_new_le_properties_from_ibml_catagory(LeDesktopContextRec * dc,
							 IbmlCatagory * ibml_catagory)
{
    IbmlElement *ibml_element;
    IbmlProperty *ibml_property;

    int i, j;

    char *id, *scope;
    char *name, *value, *options;

    if (dc == NULL)
	return (LE_FAIL);

    if (ibml_catagory == NULL)
	return (LE_FAIL);

    if (ibml_catagory->num_elements <= 0)
	return (LE_FAIL);

    DEBUG_printf("Begin le_desktop_profile_new_le_properties_from_ibml_catagory()\n");
    for (i = 0; i < ibml_catagory->num_elements; i++) {
	ibml_element = ibml_catagory->elements[i];
	if (!ibml_element)
	    continue;

	id = (char *) ibml_element->id;
	scope = (char *) ibml_element->scope;
	DEBUG_printf("id:%s, scope:%s\n", id ? id : "NULL",
		     scope ? scope : "NULL");
	if (!id || !*id)
	    continue;

	if (strcasecmp(id, "iiim_properties"))
	    continue;

	for (j = 0; j < ibml_element->num_properties; j++) {
	    ibml_property = ibml_element->properties[j];
	    if (!ibml_property)
		continue;

	    name = (char *) ibml_property->name;
	    if (!name || !*name)
		continue;

	    value = (char *) ibml_property->value;
	    if (!value || !*value)
		continue;

	    if (!strcasecmp(name, "time_stamp")) {
		char *time_stamp_str = (char *) value;
		dc->time_stamp = atol(time_stamp_str);
	    } else if (!strcasecmp(name, "shortcutkey_vkb")) {
		char *vkb_key_str = (char *) value;
		dc->shortcutkey_vkb = vkb_key_str[0];
	    }
	}
    }

    return (LE_OK);
}

int le_desktop_profile_new_imeengines_from_ibml_catagory(LeDesktopContextRec * dc,
							 IbmlCatagory * ibml_catagory,
							 int need_sort)
{
    IbmlElement *ibml_element;
    IbmlProperty *ibml_property;

    int i, j, k;
    int current_ime_module_id;
    ImeModuleContextRec *current_ime_module_context;
    ImePropertyListRec *pl;

    char *id, *scope;
    char *name, *value, *options;

    if (dc == NULL || dc->ime_modules == NULL)
	return (LE_FAIL);

    if (ibml_catagory == NULL)
	return (LE_FAIL);

    if (ibml_catagory->num_elements <= 0)
	return (LE_FAIL);

    DEBUG_printf("Begin le_desktop_profile_new_imeengines_from_ibml_catagory()\n");
    current_ime_module_id = 0;
    for (i = 0; i < ibml_catagory->num_elements; i++) {
	char *uuid = NULL;
	char *enable_str = NULL;
	int enable_value;

	ibml_element = ibml_catagory->elements[i];
	if (!ibml_element)
	    continue;

	id = (char *) ibml_element->id;
	scope = (char *) ibml_element->scope;
	DEBUG_printf("id:%s, scope:%s\n", id ? id : "NULL",
		     scope ? scope : "NULL");
	if (!id || !*id)
	    continue;

	uuid = id;

	current_ime_module_context = NULL;
	for (j = current_ime_module_id; j < dc->num_ime_modules; j++) {
	    ImeModuleContextRec *ime_module_context = dc->ime_modules[j];

	    if (!ime_module_context || !ime_module_context->ime_module)
		continue;

	    if (!strcasecmp
		(uuid, ime_module_context->ime_module->info->uuid)) {
		if (need_sort) {
		    for (k = j; k > current_ime_module_id; k--)
		        dc->ime_modules[k] = dc->ime_modules[k - 1];

		    dc->ime_modules[current_ime_module_id] =
		        ime_module_context;
		    current_ime_module_id++;
		}
		current_ime_module_context = ime_module_context;
		break;
	    }
	}

	if (current_ime_module_context == NULL)
	    continue;

	pl = current_ime_module_context->pl;

	for (j = 0; j < ibml_element->num_properties; j++) {
	    ibml_property = ibml_element->properties[j];
	    if (!ibml_property)
		continue;

	    name = (char *) ibml_property->name;
	    if (!name || !*name)
		continue;

	    value = (char *) ibml_property->value;
	    if (!value || !*value)
		continue;

	    if (!strcasecmp(name, "enabled")) {
		enable_str = (char *) value;

		enable_value = 1;
		if (enable_str && *enable_str) {
		    if (!strcasecmp(enable_str, "0") ||
			!strcasecmp(enable_str, "false"))
			enable_value = 0;
		}

		current_ime_module_context->enabled = enable_value;
		continue;
	    }

	    if (pl != NULL) {
	        for (k = 0; k < pl->count; k ++) {
		    ImePropertyRec *pi = &(pl->properties[k]);
		    if (pi == NULL || pi->key == NULL)
		        continue;

		    if (!strcmp(name, pi->key)) {
		        pi->value.int_value = atoi(value);
		    }
	        }
	    }
	}
    }

    return (LE_OK);
}

#define LE_PROPERTIES_CATAGORY		"le_settings"
#define ENGINE_PROPERTIES_CATAGORY	"engine_properties"
#define ALL_ENGINE_CATAGORY		"all_engines"

int le_desktop_profile_new_from_memory(LeDesktopContextRec * dc, char *buf,
				    int size)
{
    IbmlData *ibml_data;
    IbmlCatagory *ibml_catagory;
    int i;
    int ret = LE_OK;
    int need_sort;

    if (dc == NULL)
	return (LE_FAIL);
    if (buf == NULL || size <= 0)
	return (LE_FAIL);

    ibml_data = (IbmlData *) imbean_config_new_from_memory(buf, size);
    if (ibml_data == NULL)
	return (LE_FAIL);

    for (i = 0; i < ibml_data->num_catagories; i++) {
	ibml_catagory = ibml_data->catagories[i];

	if (!ibml_catagory->scope || !*ibml_catagory->scope)
	    continue;

	if (!strcasecmp(ibml_catagory->scope, ALL_ENGINE_CATAGORY)) {
	    need_sort = 1;
	    ret = le_desktop_profile_new_imeengines_from_ibml_catagory(dc, 
						       ibml_catagory, need_sort);
	} else if (!strcasecmp(ibml_catagory->scope, ENGINE_PROPERTIES_CATAGORY)) {
	    need_sort = 0;
	    ret = le_desktop_profile_new_imeengines_from_ibml_catagory(dc, 
						       ibml_catagory, need_sort);
	} else if (!strcasecmp(ibml_catagory->scope, LE_PROPERTIES_CATAGORY)) {
	    ret = le_desktop_profile_new_le_properties_from_ibml_catagory(dc, 
						       ibml_catagory);
	}
    }

    ibml_data_free(ibml_data);
    return (ret);
}

#define BUF_LEN   4196
char *le_desktop_profile_write_to_memory(LeDesktopContextRec * dc)
{
    xmlDocPtr doc;
    xmlNodePtr root;
    xmlNodePtr im_node;
    xmlNodePtr imbean_node;
    xmlNodePtr property_node;
    xmlChar *xmlbuf = NULL;
    char utf8_buf[BUF_LEN];
    int size = 0;
    int i;

    if (dc == NULL || dc->ime_modules == NULL)
	return (NULL);

    doc = xmlNewDoc("1.0");

    root = xmlNewNode(NULL, IBML_ELEMENT_ROOT);
    xmlSetProp(root, IBML_ELEMENT_SCOPE, LE_NAME);
    xmlDocSetRootElement(doc, root);

    doc->children = root;

    im_node = xmlNewChild(root, NULL, IBML_ELEMENT_CATAGORY, NULL);
    xmlSetProp(im_node, IBML_ELEMENT_SCOPE, LE_PROPERTIES_CATAGORY);

    imbean_node = xmlNewChild(im_node, NULL, IBML_ELEMENT_IMBEAN, NULL);
    xmlSetProp(imbean_node, IBML_ELEMENT_IMBEAN_ID, "iiim_properties");
    property_node =
	xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY, NULL);
    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME, "time_stamp");
    snprintf(utf8_buf, BUF_LEN, "%d", le_info->time_stamp);
    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE, utf8_buf);

    property_node =
	xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY, NULL);
    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME, "shortcutkey_vkb");
    snprintf(utf8_buf, BUF_LEN, "%c", dc->shortcutkey_vkb);
    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE, utf8_buf);

    im_node = xmlNewChild(root, NULL, IBML_ELEMENT_CATAGORY, NULL);
    xmlSetProp(im_node, IBML_ELEMENT_SCOPE, ALL_ENGINE_CATAGORY);

    for (i = 0; i < dc->num_ime_modules; i++) {
	ImeModuleRec *ime_module;
	ImeInfoRec *ime_info;
	ImeModuleContextRec *ime_module_context = dc->ime_modules[i];
	ImePropertyListRec *pl;

	int encoding;
	int enabled_value;
	char *enabled_str;

	char *tmp_ptr, *name_str;
	int from_len, to_left, ret;

	if (ime_module_context == NULL)
	    continue;

	ime_module = ime_module_context->ime_module;
	if (ime_module == NULL)
	    continue;

	ime_info = ime_module->info;
	if (ime_info == NULL ||
	    ime_info->uuid == NULL ||
	    ime_info->name == NULL || ime_info->author == NULL)
	    continue;

	encoding = ime_info->encoding;
	enabled_value = ime_module_context->enabled;

	imbean_node =
	    xmlNewChild(im_node, NULL, IBML_ELEMENT_IMBEAN, NULL);
	xmlSetProp(imbean_node, IBML_ELEMENT_IMBEAN_ID,
		   (char *) ime_info->uuid);

	name_str = (char *) ime_info->name;
	from_len = strlen(name_str);
	to_left = BUF_LEN;
	tmp_ptr = utf8_buf;
	memset(utf8_buf, 0, BUF_LEN);
	ret = Convert_Native_To_UTF8(encoding,
				     name_str,
				     from_len,
				     (char **) &tmp_ptr,
				     (size_t *) & to_left);

	if (ret == -1)
	    continue;

	property_node =
	    xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY, NULL);
	xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME, "name");
	xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE, utf8_buf);

	name_str = (char *) ime_info->author;
	from_len = strlen(name_str);
	to_left = BUF_LEN;
	tmp_ptr = utf8_buf;
	memset(utf8_buf, 0, BUF_LEN);
	ret = Convert_Native_To_UTF8(encoding,
				     name_str,
				     from_len,
				     (char **) &tmp_ptr,
				     (size_t *) & to_left);

	if (ret == -1)
	    continue;

	property_node =
	    xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY, NULL);
	xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME, "author");
	xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE, utf8_buf);

	snprintf(utf8_buf, BUF_LEN, "%d", ime_info->version);
	property_node =
	    xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY, NULL);
	xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME, "version");
	xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE, utf8_buf);

	if (ime_info->copyright) {
	    name_str = (char *) ime_info->copyright;
	    from_len = strlen(name_str);
	    to_left = BUF_LEN;
	    tmp_ptr = utf8_buf;
	    memset(utf8_buf, 0, BUF_LEN);
	    ret = Convert_Native_To_UTF8(encoding,
					 name_str,
					 from_len,
					 (char **) &tmp_ptr,
					 (size_t *) & to_left);

	    if (ret == -1)
		continue;

	    property_node =
		xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY,
			    NULL);
	    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME,
		       "copyright");
	    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE,
		       utf8_buf);
	}

	if (ime_info->hinting) {
	    name_str = (char *) ime_info->hinting;
	    from_len = strlen(name_str);
	    to_left = BUF_LEN;
	    tmp_ptr = utf8_buf;
	    memset(utf8_buf, 0, BUF_LEN);
	    ret = Convert_Native_To_UTF8(encoding,
					 name_str,
					 from_len,
					 (char **) &tmp_ptr,
					 (size_t *) & to_left);

	    if (ret == -1)
		continue;

	    property_node =
		xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY,
			    NULL);
	    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME,
		       "hinting");
	    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE,
		       utf8_buf);
	}

	if (ime_info->icon_file) {
	    property_node =
		xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY,
			    NULL);
	    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME,
		       "icon_file");
	    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE,
		       ime_info->icon_file);
	}

	property_node =
	    xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY, NULL);
	xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME, "enabled");
	enabled_str = "true";
	if (enabled_value == 0)
	    enabled_str = "false";
	xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE,
		   enabled_str);

	DEBUG_printf("ime_name: %s\n", ime_info->uuid);
	pl = ime_module_context->pl;
	if (pl == NULL)
	    pl = ime_info->pl;

	if (pl != NULL) {
	    int j;
	    for (j = 0; j < pl->count; j++) {
		ImeProperty ime_property;
		char options_str[BUF_LEN];
		char options_type[56];
		char options_value[10];

		ime_property = &(pl->properties[j]);
		if (ime_property->name == NULL ||
		    ime_property->key == NULL)
		    continue;

		property_node =
		    xmlNewChild(imbean_node, NULL, IBML_ELEMENT_PROPERTY,
				NULL);
		xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_NAME,
			   ime_property->key);

		options_str[0] = 0;
		options_type[0] = 0;
		options_value[0] = '0';
		options_value[1] = 0;
		if (ime_property->type == ImeProperty_Selection) {
		    char **value_ptr;
		    int k;
		    strcat(options_str, ime_property->name);
		    value_ptr = ime_property->range.multiString_range;
		    if (value_ptr != NULL) {
			for (k = 0; value_ptr[k] != NULL; k++) {
			    strcat(options_str, "/");
			    strcat(options_str, value_ptr[k]);
			}
		    }
		    strcat(options_type, "ImeProperty_Selection");
		} else if (ime_property->type == ImeProperty_Toggle) {
		    strcat(options_str, ime_property->name);
		    strcat(options_type, "ImeProperty_Toggle");
		} else if (ime_property->type == ImeProperty_Int) {
		    char value[12];
		    strcat(options_str, ime_property->name);
		    strcat(options_str, "/");
		    snprintf(value, 12, "%d/%d",
			    ime_property->range.int_range.min,
			    ime_property->range.int_range.max);
		    strcat(options_str, value);
		    strcat(options_type, "ImeProperty_Int");
		}

		snprintf(options_value, 10, "%d", ime_property->value.int_value);

#if DEBUG
		printf("options_str: %s, options_type: %s, options_value: %s\n",
			     options_str, options_type, options_value);
#endif
		if (*options_str && *options_type) {
		    encoding = ime_property->encode;
		    name_str = (char *) options_str;
		    from_len = strlen(name_str);
		    to_left = BUF_LEN;
		    tmp_ptr = utf8_buf;
		    memset(utf8_buf, 0, BUF_LEN);
		    ret = Convert_Native_To_UTF8(encoding,
						 name_str,
						 from_len,
						 (char **) &tmp_ptr,
						 (size_t *) & to_left);

		    if (ret == -1)
			continue;

		    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_OPTIONS,
			       utf8_buf);
		    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_TYPE,
			       options_type);
		    xmlSetProp(property_node, IBML_ELEMENT_PROPERTY_VALUE,
			       options_value);
		}
	    }
	}
    }

    xmlDocDumpFormatMemoryEnc(doc, &xmlbuf, &size, "UTF-8", 1);

    xmlFreeDoc(doc);

    return (xmlbuf);
}

/****************************************************************************/
/*                         LE Desktop                                       */
/****************************************************************************/
LeDesktopContextRec *le_desktop_create(iml_desktop_t * desktop)
{
    LeDesktopContextRec *le_desktop_context = NULL;
    int num_ime_modules, i;

    le_desktop_context = (LeDesktopContextRec *) le_desktop_context_new();
    DEBUG_printf("le_desktop_create ===== %p\n", le_desktop_context);

    le_desktop_context_print(le_desktop_context);

    desktop->specific_data = (void *) le_desktop_context;

    return (le_desktop_context);
}

LeResult le_desktop_destroy(iml_desktop_t * desktop)
{
    LeDesktopContextRec *le_desktop_context =
	(LeDesktopContextRec *) desktop->specific_data;

    le_desktop_context_destroy(le_desktop_context);

    desktop->specific_data = NULL;

    return (LE_OK);
}
