/* This file is part of the Project Athena Zephyr Notification System.
 * It contains source for the ZGetCharset function.
 *
 *	Created by:	Karl Ramm
 *
 *	$Id: 14aec28f7dd127eb7827eabaca893a9f6c4f2306 $
 *
 *	Copyright (c) 2009 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */

#ifndef lint
static const char rcsid_charset_c[] = "$Id: 14aec28f7dd127eb7827eabaca893a9f6c4f2306 $";
#endif /* lint */

#include <internal.h>

#include <string.h>
#include <locale.h>
#include <langinfo.h>
#include <ctype.h>
#include <iconv.h>
#include <errno.h>

const char *
ZGetCharsetString(char *charset)
{
    char *p;
    static int once = 1;
	
    if (charset == NULL)
	charset = getenv("ZEPHYR_CHARSET");

    if (charset == NULL) {
	if (once) {
	    setlocale(LC_ALL, "");
	    once = 0;
	}
	charset = nl_langinfo(CODESET);
    }

    if (charset == NULL)
	return ZCHARSET_UNKNOWN;

    charset = strdup(charset);

    for (p = charset; *p; p++)
	*p = toupper(*p);

    return charset;
}

unsigned short
ZGetCharset(char *charset)
{
    short retval;
	
    charset = (char *)ZGetCharsetString(charset);
    if (!strcmp(charset, "NONE") || !strcmp(charset, "UNKNOWN"))
	retval = ZCHARSET_UNKNOWN;
    else if (!strcmp(charset, "ANSI_X3.4-1968"))
	retval = ZCHARSET_ISO_8859_1; /* A hack. */
    else if (!strcmp(charset, "ISO-8859-1"))
	retval = ZCHARSET_ISO_8859_1;
    else if (!strcmp(charset, "UTF-8"))
	retval = ZCHARSET_UTF_8;
    else
	retval = ZCHARSET_UNKNOWN;

    free(charset);
    return retval;
}

const char *
ZCharsetToString(unsigned short charset)
{
    if (charset == ZCHARSET_UNKNOWN)
	return "UNKNOWN";
    else if (charset == ZCHARSET_ISO_8859_1)
	return "ISO-8859-1";
    else if (charset == ZCHARSET_UTF_8)
	return "UTF-8";
    return "UNKNOWN";
}

Code_t
ZTransliterate(char *in, int inlen, char *inset, char *outset, char **out, int *outlen)
{
    iconv_t ih;
    char *outset_t, *inp, *outp;
    int retval;
    size_t size, inleft, outleft;

    *out = NULL;
    *outlen = 0;

    outset_t = malloc(strlen(outset) + 11);
    if (outset_t == NULL)
	return errno;
    sprintf(outset_t, "%s//TRANSLIT", outset);

    ih = iconv_open(outset_t, inset);

    free(outset_t);

    if (ih == (iconv_t)-1)
	return errno;

    size = inlen; /* doubling this should be enough, but.. */
    do {
	size = size * 2;

	*out = malloc(size);
	if (*out == NULL) {
	    iconv_close(ih);
	    return errno;
	}

	inleft = inlen;
	outleft = size;

	inp = in;
	outp = *out;

	retval = iconv(ih, &inp, &inleft, &outp, &outleft);
	if (retval < 0)
	    free(*out);
    } while (retval < 0 && errno == E2BIG);

    iconv_close(ih);

    if (retval < 0)
	return errno;

    *outlen = size - outleft;

    return ZERR_NONE;
}
