/*
 * Copyright (c) 1999 Sun Microsystems, Inc.
 * Copyright (c) 1999 Nihon Sun Microsystems K.K.
 * All rights reserved.
 */

/*
 * "$Id: utf16_ct_map_set.c,v 1.1.1.1 2000/10/29 16:45:20 himi Exp $"
 */

#pragma ident	"@(#)utf16_ct_map_set.c 1.8	99/07/05 SMI"


#include "config.h"

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <sys/param.h>

#include "csconv.h"
#include "csc_conf_info.h"
#include "utf16_ct_map.h"
#include "utf16_ct_map_set.h"
#include "ct_conf.h"


#define	CSC_CT_DIR "compoundtext/"


#define	CS_CKN	"ct_ckn"
#define	CS_CNK	"ct_cnk"
#define	CS_KCN	"ct_kcn"
#define	CS_KNC	"ct_knc"
#define	CS_NCK	"ct_nck"
#define	CS_NKC	"ct_nkc"


extern csc_utf16_ct_map_t	csc_utf16_iso8859_l_map;
extern csc_utf16_ct_map_t	csc_utf16_jisx0201_r_map;
extern csc_utf16_ct_map_t	csc_utf16_jisx0201_l_map;

extern csc_utf16_ct_map_t	csc_utf16_iso8859_1_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_2_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_3_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_4_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_5_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_6_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_7_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_8_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_9_r_map;
extern csc_utf16_ct_map_t	csc_utf16_iso8859_15_r_map;

extern csc_utf16_ct_map_t	csc_utf16_gb2312_r_map;
extern csc_utf16_ct_map_t	csc_utf16_jisx0208_r_map;
extern csc_utf16_ct_map_t	csc_utf16_ksc5601_l_map;
extern csc_utf16_ct_map_t	csc_utf16_ksc5601_r_map;
extern csc_utf16_ct_map_t	csc_utf16_jisx0212_r_map;

extern csc_utf16_ct_map_t	csc_utf16_ksc5601_1992_3_map;
extern csc_utf16_ct_map_t	csc_utf16_sunudcja_1997_0_map;
extern csc_utf16_ct_map_t	csc_utf16_big5_map;

extern csc_utf16_ct_map_t	csc_utf16_unicode_fs_map;

static const csc_utf16_ct_map_t *	csc_ct_map_ckn[] = {
	&csc_utf16_iso8859_l_map,
	&csc_utf16_iso8859_1_r_map,
	&csc_utf16_iso8859_5_r_map,
	&csc_utf16_iso8859_7_r_map,
	&csc_utf16_iso8859_2_r_map,
	&csc_utf16_iso8859_4_r_map,
	&csc_utf16_iso8859_9_r_map,
	&csc_utf16_iso8859_15_r_map,
	&csc_utf16_gb2312_r_map,
	&csc_utf16_big5_map,
	&csc_utf16_ksc5601_1992_3_map,
	&csc_utf16_jisx0208_r_map,
	&csc_utf16_jisx0201_r_map,
	&csc_utf16_jisx0212_r_map,
	&csc_utf16_jisx0201_l_map,
	&csc_utf16_iso8859_6_r_map,
	&csc_utf16_iso8859_8_r_map,
	&csc_utf16_sunudcja_1997_0_map,
	&csc_utf16_iso8859_3_r_map,
	&csc_utf16_unicode_fs_map,
	NULL
};

static const csc_utf16_ct_map_t *	csc_ct_map_cnk[] = {
	&csc_utf16_iso8859_l_map,
	&csc_utf16_iso8859_1_r_map,
	&csc_utf16_iso8859_5_r_map,
	&csc_utf16_iso8859_7_r_map,
	&csc_utf16_iso8859_2_r_map,
	&csc_utf16_iso8859_4_r_map,
	&csc_utf16_iso8859_9_r_map,
	&csc_utf16_iso8859_15_r_map,
	&csc_utf16_gb2312_r_map,
	&csc_utf16_big5_map,
	&csc_utf16_jisx0208_r_map,
	&csc_utf16_jisx0201_r_map,
	&csc_utf16_jisx0212_r_map,
	&csc_utf16_ksc5601_1992_3_map,
	&csc_utf16_jisx0201_l_map,
	&csc_utf16_iso8859_6_r_map,
	&csc_utf16_iso8859_8_r_map,
	&csc_utf16_sunudcja_1997_0_map,
	&csc_utf16_iso8859_3_r_map,
	&csc_utf16_unicode_fs_map,
	NULL
};

static const csc_utf16_ct_map_t *	csc_ct_map_kcn[] = {
	&csc_utf16_iso8859_l_map,
	&csc_utf16_iso8859_1_r_map,
	&csc_utf16_iso8859_5_r_map,
	&csc_utf16_iso8859_7_r_map,
	&csc_utf16_iso8859_2_r_map,
	&csc_utf16_iso8859_4_r_map,
	&csc_utf16_iso8859_9_r_map,
	&csc_utf16_iso8859_15_r_map,
	&csc_utf16_ksc5601_1992_3_map,
	&csc_utf16_gb2312_r_map,
	&csc_utf16_big5_map,
	&csc_utf16_jisx0208_r_map,
	&csc_utf16_jisx0201_r_map,
	&csc_utf16_jisx0212_r_map,
	&csc_utf16_jisx0201_l_map,
	&csc_utf16_iso8859_6_r_map,
	&csc_utf16_iso8859_8_r_map,
	&csc_utf16_sunudcja_1997_0_map,
	&csc_utf16_iso8859_3_r_map,
	&csc_utf16_unicode_fs_map,
	NULL
};

static const csc_utf16_ct_map_t *	csc_ct_map_knc[] = {
	&csc_utf16_iso8859_l_map,
	&csc_utf16_iso8859_1_r_map,
	&csc_utf16_iso8859_5_r_map,
	&csc_utf16_iso8859_7_r_map,
	&csc_utf16_iso8859_2_r_map,
	&csc_utf16_iso8859_4_r_map,
	&csc_utf16_iso8859_9_r_map,
	&csc_utf16_iso8859_15_r_map,
	&csc_utf16_ksc5601_1992_3_map,
	&csc_utf16_jisx0208_r_map,
	&csc_utf16_jisx0201_r_map,
	&csc_utf16_jisx0212_r_map,
	&csc_utf16_gb2312_r_map,
	&csc_utf16_big5_map,
	&csc_utf16_jisx0201_l_map,
	&csc_utf16_iso8859_6_r_map,
	&csc_utf16_iso8859_8_r_map,
	&csc_utf16_sunudcja_1997_0_map,
	&csc_utf16_iso8859_3_r_map,
	&csc_utf16_unicode_fs_map,
	NULL
};

static const csc_utf16_ct_map_t *	csc_ct_map_nck[] = {
	&csc_utf16_iso8859_l_map,
	&csc_utf16_jisx0201_l_map,
	&csc_utf16_iso8859_1_r_map,
	&csc_utf16_iso8859_5_r_map,
	&csc_utf16_iso8859_7_r_map,
	&csc_utf16_iso8859_2_r_map,
	&csc_utf16_iso8859_4_r_map,
	&csc_utf16_iso8859_9_r_map,
	&csc_utf16_iso8859_15_r_map,
	&csc_utf16_jisx0208_r_map,
	&csc_utf16_jisx0201_r_map,
	&csc_utf16_jisx0212_r_map,
	&csc_utf16_gb2312_r_map,
	&csc_utf16_big5_map,
	&csc_utf16_ksc5601_1992_3_map,
	&csc_utf16_iso8859_6_r_map,
	&csc_utf16_iso8859_8_r_map,
	&csc_utf16_sunudcja_1997_0_map,
	&csc_utf16_iso8859_3_r_map,
	&csc_utf16_unicode_fs_map,
	NULL
};

static const csc_utf16_ct_map_t *	csc_ct_map_nkc[] = {
	&csc_utf16_iso8859_l_map,
	&csc_utf16_jisx0201_l_map,
	&csc_utf16_iso8859_1_r_map,
	&csc_utf16_iso8859_5_r_map,
	&csc_utf16_iso8859_7_r_map,
	&csc_utf16_iso8859_2_r_map,
	&csc_utf16_iso8859_4_r_map,
	&csc_utf16_iso8859_9_r_map,
	&csc_utf16_iso8859_15_r_map,
	&csc_utf16_jisx0208_r_map,
	&csc_utf16_jisx0201_r_map,
	&csc_utf16_jisx0212_r_map,
	&csc_utf16_ksc5601_1992_3_map,
	&csc_utf16_gb2312_r_map,
	&csc_utf16_big5_map,
	&csc_utf16_iso8859_6_r_map,
	&csc_utf16_iso8859_8_r_map,
	&csc_utf16_sunudcja_1997_0_map,
	&csc_utf16_iso8859_3_r_map,
	&csc_utf16_unicode_fs_map,
	NULL
};

const csc_utf16_ct_map_set_t	utf16_ct_map_set[] = {
	{CS_CKN,
	 &csc_utf16_iso8859_l_map,
	 csc_ct_map_ckn},
	{CS_CNK,
	 &csc_utf16_iso8859_l_map,
	 csc_ct_map_cnk},
	{CS_KCN,
	 &csc_utf16_iso8859_l_map,
	 csc_ct_map_kcn},
	{CS_KNC,
	 &csc_utf16_iso8859_l_map,
	 csc_ct_map_knc},
	{CS_NCK,
	 &csc_utf16_iso8859_l_map,
	 csc_ct_map_nck},
	{CS_NKC,
	 &csc_utf16_iso8859_l_map,
	 csc_ct_map_nkc},
	{NULL, NULL, NULL}
};

const csc_utf16_ct_map_set_t	utf16_ct_map_set_default = {
	CS_NKC,
	&csc_utf16_iso8859_l_map,
	csc_ct_map_nkc
};


extern const csc_utf16_ct_map_t * csc_utf16_national_map[];

const csc_utf16_ct_map_set_t *
utf16_ct_map_set_get(const char * id)
{
	int				i;
	char				path[MAXPATHLEN];
	char *				base_dir;
	int				len;
	csc_conf_file_t *		conf_file;
	csc_conf_str_t			conf_str[2];
	int				ret;
	int				num;
	int				ucm_num;
	csc_utf16_ct_map_set_t *	ucms;
	const csc_utf16_ct_map_t **	ucmr;
	const csc_utf16_ct_map_t *	ucm_default;
	const csc_utf16_ct_map_t *	ucm_buf[32];
	const csc_utf16_ct_map_t **	ucm;
	const csc_utf16_ct_map_t **	ucm_new;
	size_t				size;
	const csc_ct_conf_def_t *	ct_conf;

	ucms = NULL;
	ucmr = NULL;
	ucm = NULL;
	ct_conf = NULL;

	base_dir = CSC_BASE_DIR_DEFAULT CSC_CT_DIR;

	len = strlen(base_dir);
	if (MAXPATHLEN <= (len + strlen(id))) {
		return &utf16_ct_map_set_default;
	}

	strcpy(path, base_dir);
	strcpy(path + len, id);

	conf_file = csc_conf_open(path, 0, NULL, 0);

	ucm_default = NULL;

	do {
		if ((ret = csc_conf_read(conf_file, conf_str, 2)) < 2) {
			if (NULL != ct_conf) {
				break;
			}

			csc_conf_close(conf_file);
			conf_file = NULL;

			for (ct_conf = csc_ct_conf_internal;
			     NULL != ct_conf->name; ct_conf++) {
				if (0 == strcmp(ct_conf->name, id)) {
					break;
				}
			}
			if (NULL == ct_conf->name) {
				break;
			}
			conf_file = csc_conf_open(NULL, 0,
						  ct_conf->conf,
						  ct_conf->length);
			continue;
		}
		for (ucmr = csc_utf16_national_map; NULL != *ucmr; ucmr++) {
			if ((0 == csc_strcmp((*ucmr)->name, conf_str + 0)) &&
			    (0 == csc_strcmp((*ucmr)->gl_gr, conf_str + 1))) {
				ucm_default = *ucmr;
				break;
			}
		}
		if (NULL == ucm_default) {
			break;
		}

		ucm = ucm_buf;
		ucm_num = ((sizeof (ucm_buf)) / (sizeof (csc_utf16_ct_map_t *)));

		num = 0;

		for (;;) {
			ret = csc_conf_read(conf_file, conf_str, 2);
			if (ret < 2) {
				break;
			}

			if (ucm_num <= (num + 1)) {
				ucm_num *= 2;
				size = ((sizeof (csc_utf16_ct_map_t *)) *
					ucm_num);

				if (ucm_buf == ucm) {
					if (NULL == (ucm_new = malloc(size))) {
						break;
					}
					memcpy(ucm_new, ucm, size);
					ucm = ucm_new;
				} else {
					ucm_new = realloc((char *)ucm, size);
					if (NULL == ucm_new) {
						free(ucm);
						ucm = NULL;
						break;
					}
					ucm = ucm_new;
				}
			}

			for (ucmr = csc_utf16_national_map;
			     NULL != *ucmr; ucmr++) {
				if ((0 == csc_strcmp((*ucmr)->name,
						     conf_str + 0)) &&
				    (0 == csc_strcmp((*ucmr)->gl_gr,
						     conf_str + 1))) {
					*(ucm + num) = *ucmr;
					num++;
					break;
				}
			}
		}

		csc_conf_close(conf_file);
		conf_file = NULL;

		if (NULL == ucm) {
			break;
		}

		if (0 == num) {
			break;
		}

		*(ucm + num) = NULL;
		if (ucm_buf == ucm) {
			size = ((sizeof (csc_utf16_ct_map_t *)) * (num + 1));
			ucm_new = malloc(size);
			if (NULL == ucm_new) {
				break;
			}
			memcpy(ucm_new, ucm, size);
			ucm = ucm_new;
		}

		ucms = malloc(sizeof (csc_utf16_ct_map_set_t));
		if (NULL == ucms) {
			break;
		}

		ucms->name = strdup(id);
		if (NULL == ucms->name) {
			break;
		}

		ucms->utf16_ct_map_default = ucm_default;
		ucms->utf16_ct_map = ucm;

		return ucms;
	} while(1);

	csc_conf_close(conf_file);

	if (NULL != ucms) {
		free((char *)(ucms->name));
		free(ucms);
	}

	if (ucm_buf != ucm) {
		free(ucm);
	}

	ucms = NULL;
	for (i = 0; NULL != utf16_ct_map_set[i].name; i++) {
		if (0 == strcmp(id, utf16_ct_map_set[i].name)) {
			ucms = (csc_utf16_ct_map_set_t *)(utf16_ct_map_set + i);
			break;
		}
	}

	if (NULL == ucms) {
		return &utf16_ct_map_set_default;
	} else {
		return ucms;
	}
}


void
utf16_ct_map_set_free(csc_utf16_ct_map_set_t * map_set)
{
	int	i;

	if (&utf16_ct_map_set_default == map_set) {
		return;
	}

	for (i = 0; NULL != utf16_ct_map_set[i].name; i++) {
		if ((utf16_ct_map_set + i) == map_set) {
			return;
		}
	}

	free((void *)(map_set->name));
	free(map_set->utf16_ct_map);
	free(map_set);
	return;
}
