/*
 * Copyright (C) 1992 by Software Research Associates, Inc.
 *      Author: Y. Kawabe <kawabe@sra.co.jp>
 *
 * Permission to use, copy, modify, and distribute, and sell this software
 * and its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Software Research Associates not be
 * used in advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.  Software Research Associates
 * makes no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 */

#include <NLS/charset.h>
#include <NLS/nlsfile.h>
#include <hyperg/OS/table.h>
#include <hyperg/OS/ustring.h>
#include <string.h>
#include <stdlib.h>

#ifndef IV_CHARSET_PATH
#define IV_CHARSET_PATH         "CharSet"
#endif

/*
 * Class CharSetRep
 */

CharSetRep::CharSetRep(
    const char* name, int bytes, int cols, int chars, char final
) {
    name_ = new UniqueString(name);
    bytes_ = bytes;
    cols_ = cols;
    chars_ = chars;
    final_ = final;
}

CharSetRep::~CharSetRep() {
    delete name_;
}
			
/*
 * Class CharSetRepTable
 */

declareTable(CharSetRepTable, int, const CharSetRep*);
implementTable(CharSetRepTable, int, const CharSetRep*);

/*
 * Class CharSet
 */

CharSetRepTable	*CharSet::table_;

void CharSet::initialize () {
    if (table_ == nil) {
	table_ = new CharSetRepTable(32);
	table_->insert(
	    CharSet::ascii(), new CharSetRep("ASCII", 1, 1, 94, 'B')
	);
	table_->insert(
	    1, new CharSetRep("ISO8859-1", 1, 1, 96, 'A')
	);
	table_->insert(
	    2, new CharSetRep("ISO8859-2", 1, 1, 96 , 'B')
	);
	table_->insert(
	    3, new CharSetRep("ISO8859-3", 1, 1, 96 , 'C')
	);                                             
	table_->insert(
	    4, new CharSetRep("ISO8859-4", 1, 1, 96 , 'D')
	);                                             
	table_->insert(
	    5, new CharSetRep("ISO8859-5", 1, 1, 96 , 'L')
	);                                             
	table_->insert(
	    6, new CharSetRep("ISO8859-6", 1, 1, 96 , 'G')
	);                                             
	table_->insert(
	    7, new CharSetRep("ISO8859-7", 1, 1, 96 , 'F')
	);                                             
	table_->insert(
	    8, new CharSetRep("ISO8859-8", 1, 1, 96 , 'H')
	);                                             
	table_->insert(
	    9, new CharSetRep("ISO8859-9", 1, 1, 96 , 'M')
	);
	table_->insert(
	    10, new CharSetRep("JISX0201.1976-R", 1, 1, 94 , 'J')
	);
	table_->insert(
	    11, new CharSetRep("JISX0201.1976-K", 1, 1, 94 , 'I')
	);
	table_->insert(
	    12, new CharSetRep("JISX0208.1978", 2, 2, 94 , '@')
	);
	table_->insert(
	    13, new CharSetRep("GB2312.1980", 2, 2, 94 , 'A')
	);
	table_->insert(
	    14, new CharSetRep("JISX0208.1983", 2, 2, 94 , 'B')
	);
	table_->insert(
	    15, new CharSetRep("KSC5601.1987", 2, 2, 94 , 'C')
	);
	table_->insert(
	    16, new CharSetRep("JISX0212.1990", 2, 2, 94 , 'D')
	);
	table_->insert(
	    17, new CharSetRep("BIG5.HKU", 2, 2, 188, '-')
	);
	
	int		argc;
	const int	argsize = 64;
	char		*argv[argsize];
	nlsFile		file (IV_CHARSET_PATH);
	CharSetRep	*rep;
	int		charset;

	while ((argc = file.getline (argv, argsize)) >= 0) {
	    if (argc == 6) {
		charset = file.str2int(argv[0]);
		if (table_->find_and_remove(rep, charset)) {
		    delete rep;
		}
		rep = new CharSetRep(argv[1],
				     file.str2int(argv[2]),
				     file.str2int(argv[3]),
				     file.str2int(argv[4]),
				     argv[5][0]);
		table_->insert(charset, rep);
	    }
	}
    }
}

/*
 *	find CharSet ID
 */

CharSet_T CharSet::find (const char* name) {
    initialize();
    UniqueString uname(name);
    return find (uname);
}

CharSet_T CharSet::find (const String& name) {
    initialize();
    UniqueString uname(name);
    for (TableIterator(CharSetRepTable) i(*table_); i.more(); i.next()) {
	if (i.cur_value()->name() == uname)
	    return i.cur_key();
    }
    return -1;
}

CharSet_T CharSet::find (enum SorM n, int chars, char final) {
    initialize();
    if (n == Single) {
	for (TableIterator(CharSetRepTable) i(*table_); i.more(); i.next()) {
	    if (i.cur_value()->bytes() == 1 &&
		i.cur_value()->chars() == chars && 
		i.cur_value()->final() == final) {
		return i.cur_key();
	    }
	}
    } else {
	for (TableIterator(CharSetRepTable) i(*table_); i.more(); i.next()) {
	    if (i.cur_value()->bytes() > 1 &&
		i.cur_value()->chars() == chars &&
		i.cur_value()->final() == final) {
		return i.cur_key();
	    }
	}
    }
    return -1;
}

const CharSetRep* CharSet::rep (CharSet_T charset) {
    initialize();
    const CharSetRep *rep;
    if (table_->find(rep, charset)) {
	return rep;
    }
    return nil;
}
