#include <../source/TAL/objbase.h>

#include <../source/TAL/utables/latin1.c>

#ifdef	CONFIG_KOI8R_TABLE
#include <../source/TAL/utables/koi8_r.c>
#endif	/* CONFIG_KOI8R_TABLE */

#ifdef	CONFIG_CP866_TABLE
#include <../source/TAL/utables/cp866.c>
#endif	/* CONFIG_CP866_TABLE */

#ifdef	CONFIG_WIN1251_TABLE
#include <../source/TAL/utables/win1251.c>
#endif	/* CONFIG_WIN1251_TABLE */

#include <../source/TAL/utables/uc_alias.c>

V_LOCAL uc_charmap_desc_t known_uc_charmaps[] =
{
	{"latin1",latin1_ccd}, /* should be the first one */

#ifdef	CONFIG_KOI8R_TABLE
	{"koi8-r",koi8_r_ccd},
#endif	/* CONFIG_KOI8R_TABLE */

#ifdef	CONFIG_CP866_TABLE
	{"cp866",cp866_ccd},
#endif	/* CONFIG_CP866_TABLE */

#ifdef	CONFIG_WIN1251_TABLE
	{"win1251",win1251_ccd},
#endif	/* CONFIG_WIN1251_TABLE */

	{NULL,NULL}
};

uc_charmap_desc_p V_GLOBAL
ucGetCharmap(int cmap_num)
{
	int i;
	for(i = 0;known_uc_charmaps[i].name;i++)
		if(i == cmap_num)
			return &known_uc_charmaps[i];
	return NULL;
}

uc_char_desc_p V_GLOBAL
ucFindAscii(uc_charmap_desc_p cmap,u32_t acode)
{
	CALLER_NAME(ucFindAscii)
	uc_char_desc_p head;
	if(!cmap)
	{
		ERROR_GENERIC(error_incorrect_parameters);
		return NULL;
	}
	head = cmap->desc;
	for(;head->name;head++)
		if(head->acode == acode)
			return head;
	return NULL;
}

uc_char_desc_p V_GLOBAL
ucFindUnicode(uc_charmap_desc_p cmap,u32_t ucode)
{
	CALLER_NAME(ucFindUnicode)
	uc_char_desc_p head;
	if(!cmap)
	{
		ERROR_GENERIC(error_incorrect_parameters);
		return NULL;
	}
	head = cmap->desc;
	for(;head->name;head++)
		if(head->ucode == ucode)
			return head;
	return NULL;
}

char_p	V_GLOBAL
ucCharName(u32_t ucode)
{
	int i;
	uc_char_desc_p cd;
	STATIC_STRING(noname,"UNKNOWN")
	if(ucode < 0x80)
	{
		cd = ucFindAscii(known_uc_charmaps,ucode);
		if(!cd)
			return noname;
		return cd->name;
	}
	for(i = 1;known_uc_charmaps[i].name;i++)
	{
		cd = ucFindUnicode(known_uc_charmaps + i,ucode);
		if(cd)
			return cd->name;
	}
	return noname;
}

uc_char_desc_p V_GLOBAL
ucFindUnicodeOrAlias(uc_charmap_desc_p target_cmap,u32_t uc_orig)
{
	CALLER_NAME(ucFindUnicodeOrAlias)
	u32_t i;
	uc_alias_list_p alist;
	uc_char_desc_p dest;
	if(!target_cmap)
	{
		ERROR_GENERIC(error_incorrect_parameters);
		return NULL;
	}
	dest = ucFindUnicode(target_cmap,uc_orig);
	if(dest)
		return dest;
	alist = uni_aliases;
	for(;alist->num_alias;alist++)
	{
		if(alist->ucode != uc_orig)
			continue;
		/* found alias for uc_orig */
		for(i = 0;i < alist->num_alias;i++)
		{
			if(alist->alias[i] < 0x80) /* can be replaced by ASCII */
				dest = ucFindAscii(known_uc_charmaps,alist->alias[i]);
			if(dest)
				return dest;
			dest = ucFindUnicode(target_cmap,alist->alias[i]);
			if(dest)
				return dest;
		}
	}
	return NULL;
}

#define	CHAR_UNKNOWN	'?'

vboolean V_GLOBAL
ucAscii2AsciiTable(char_p src_cmap_name,char_p dst_cmap_name,
	u8_t transtab_ret[])
{
	CALLER_NAME(ucAscii2AsciiTable)
	u32_t i;
	uc_charmap_desc_p src_map = NULL, dst_map = NULL;
	uc_char_desc_p cd;
	if(!src_cmap_name || !dst_cmap_name || !transtab_ret)
	{
		ERROR_GENERIC(error_incorrect_parameters);
		return false;
	}
	for(i = 0;known_uc_charmaps[i].name;i++)
	{
		if(!strcmp(known_uc_charmaps[i].name,src_cmap_name))
			src_map = &known_uc_charmaps[i];
		if(!strcmp(known_uc_charmaps[i].name,dst_cmap_name))
			dst_map = &known_uc_charmaps[i];
	}
	if(!src_map)
	{
		ERROR_GENERIC("unknown source map");
		return false;
	}
	if(!dst_map)
	{
		ERROR_GENERIC("unknown destination map");
		return false;
	}
	/* lower part: one-to-one correspondence */
	for(i = 0;i < 0x80;i++)
		transtab_ret[i] = (u8_t)i;
	if(src_map == dst_map)
	{
		for(i = 0x80;i < 0xFF;i++)
			transtab_ret[i] = (u8_t)i;
		return true;
	}
	for(i = 0x80;i < 0xFF;i++)
	{
		cd = ucFindAscii(src_map,i);
		if(!cd)
		{
			transtab_ret[i] = CHAR_UNKNOWN;
			continue;
		}
		cd = ucFindUnicodeOrAlias(dst_map,cd->ucode);
		if(!cd)
			transtab_ret[i] = CHAR_UNKNOWN;
		else
			transtab_ret[i] = (u8_t)cd->acode;
	}
	return true;
}
