/*
 * Copyright (C) 1993 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.
 *
 */

/*
 * class big5CodeCvt
 */

#define big5CodeCvt _lib_nls(big5CodeCvt)

#define BIG5_OPT_ETEN	0x01    /* use eten encoding */

class big5CodeCvt : public CodeCvt {
  public:
    big5CodeCvt ();
    
  public:
    virtual CodeCvt* duplicate();
    virtual void setparam(const char*, const char*);

  public:
    virtual int get (istream&, WChar&);
    virtual int put (ostream&, const WChar&);
    
  protected:
    CharSet_T GL_ ;
    CharSet_T GR_ ;
    long      opts_;
};

big5CodeCvt::big5CodeCvt () {
    GL_ = CharSet::ascii();
    GR_ = -1;
    opts_ = 0;
}

CodeCvt* big5CodeCvt::duplicate () {
    big5CodeCvt *copy = new big5CodeCvt ();
    *copy = *this;
    return copy;
}

void big5CodeCvt::setparam (const char* key, const char* value) {
    if (strcmp (key, "GL") == 0) {
        GL_ = CharSet::find(value);
    } else if (strcmp (key, "GR") == 0) {
        GR_ = CharSet::find(value);
    } else if (strcmp (key, "OPT") == 0) {
	if (strcmp (value, "ETEN") == 0) {
            opts_ |= BIG5_OPT_ETEN;
        }
    }
}

//
// read WChar from input stream
//

int big5CodeCvt::get (istream& is, WChar& wc) {
    register int	ch = is.get();
    if (ch != EOF) {
	if (ch > 0x20 && ch < 0x7f) {				/* GL */
	    wc.set(ch, GL_);
            return 1;
        } else if (is.good() && ch >= 0xa0 && ch <= 0xff) {	/* GR */
	    register int	ch2 = is.get();
	     register unsigned char c1 = ch & 0xff, c2 = ch2 & 0xff;
	    if (opts_ & BIG5_OPT_ETEN) {
		;
	    }
	    wc.set((c1 << 8) | c2, GR_);
	    return 2;
	} else {
	    wc.set(ch, CharSet::ascii());
	    return 1;
	}
    }
    return -1;				/* return EOF */
}

//
// write WChar to output stream
//

int big5CodeCvt::put (ostream& os, const WChar& c) {
    if (c.value() == EOF) {
	return 0;
    } if (c.charset() == CharSet::ascii()) {
	os.put(c.charcode());
	return 1;
    } else if (c.charset() == GL_) {
	os.put(c.charcode());
	return 1;
    } else if (c.charset() == GR_) {
	register int code = c.charcode();
	register unsigned char c1 = (code>>8) & 0xff;
	register unsigned char c2 = code & 0xff;
	if (opts_ & BIG5_OPT_ETEN) {
	    ;
	}
	os.put(c1);
	os.put(c2);
	return 2;
    }
    return 0;
}

