/**
 *  @file   unicoder.h
 *  @author Perry Rapp, Creator, 2003-2004
 *  @date   Created: 2003-10
 *  @date   Edited:  2006-02-20 (Perry Rapp)
 *
 *  @brief  Declaration of utility unicode conversion routines
 */ 
// ID line follows -- this is updated by SVN
// $Id: unicoder.h 4959 2008-01-26 00:05:00Z kimmov $

#ifndef unicoder_h_included
#define unicoder_h_included

namespace ucr {

struct buffer {
	unsigned char * ptr;
	unsigned int size;
	unsigned int used;

	buffer(unsigned int needed);
	~buffer();
	void resize(unsigned int needed);
};

struct CodePageInfo
{
	int codepage;
	wchar_t desc[256];
    wchar_t fixedWidthFont[256];
    char bGDICharset;
};

struct IExconverter
{
	virtual bool initialize() = 0;
	virtual bool convert(int srcCodepage, int dstCodepage, const unsigned char * src, int * srcbytes, unsigned char * dest, int * destbytes) = 0;
	virtual bool convertFromUnicode(int dstCodepage, const wchar_t * src, int * srcchars, char * dest, int *destbytes) = 0;
	virtual bool convertToUnicode(int srcCodepage, const char * src, int * srcbytes, wchar_t * dest, int *destchars) = 0;
	virtual int detectInputCodepage(int autodetectType, int defcodepage, const char *data, int size) = 0;
	virtual int enumCodePages(CodePageInfo *cpinfo, int count) = 0;
	virtual bool getCodepageFromCharsetName(LPCTSTR pszCharsetName, int *pCodepage) = 0;
	virtual bool getCodepageDescription(int codepage, LPTSTR pszCharsetName) = 0;
	virtual bool isValidCodepage(int codepage) = 0;
	virtual bool getCodePageInfo(int codePage, CodePageInfo *pCodePageInfo) = 0;
};

IExconverter *createConverterMLang();

class IExconverterPtr {
private:
	IExconverter *m_ptr;
public:
	IExconverterPtr(IExconverter *pexconv) { m_ptr = pexconv;	}
	~IExconverterPtr()                     { if (m_ptr) delete m_ptr; }
	operator IExconverter * ( void ) const { return m_ptr ; }
	IExconverter *operator->( void ) const { return m_ptr ; }
};

/** @brief Known Unicode encodings. */
typedef enum
{
	NONE = 0,  /**< No unicode. */
	UCS2LE,    /**< UCS-2 little endian. */
	UCS2BE,    /**< UCS-2 big endian. */
	UTF8,      /**< UTF-8. */
} UNICODESET;
CString GetUnicodesetName(UNICODESET codeset);

int Ucs4_to_Utf8(UINT unich, unsigned char * utf8);
int Utf8len_fromLeadByte(unsigned char ch);
int Utf8len_fromCodepoint(UINT ch);
UINT Utf8len_of_string(LPCWSTR text, int size);
UINT stringlen_of_utf8(LPCSTR text, int size);
UINT GetUtf8Char(unsigned char * str);
int to_utf8_advance(UINT u, unsigned char * &lpd);
void maketchar(CString & ch, UINT unich, bool & lossy);
int writeBom(LPVOID dest, UNICODESET unicoding);
UINT get_unicode_char(unsigned char * ptr, UNICODESET unicoding, int codepage=0);
void maketstring(CString & line, LPCSTR lpd, UINT len, int codepage, bool * lossy);
void maketchar(CString & ch, UINT unich, bool & lossy, UINT codepage);
UINT byteToUnicode(unsigned char ch);
UINT byteToUnicode(unsigned char ch, UINT codepage);
void getInternalEncoding(UNICODESET * unicoding, int * codepage);

// generic function to do all conversions
bool convert(UNICODESET unicoding1, int codepage1, const unsigned char * src, int srcbytes, UNICODESET unicoding2, int codepage2, buffer * dest);
bool convert(int codepage1, const unsigned char * src, int srcbytes, int codepage2, buffer * dest);

unsigned char *convertTtoUTF8(buffer * dest, LPCTSTR * src, int srcbytes = -1);
unsigned char *convertTtoUTF8(LPCTSTR * src, int srcbytes/* = -1*/);
TCHAR *convertUTF8toT(buffer * dest, LPCSTR * src, int srcbytes = -1);
TCHAR *convertUTF8toT(LPCSTR * src, int srcbytes/* = -1*/);
void dealloc(void *ptr);

int CrossConvert(LPCSTR src, UINT srclen, LPSTR dest, UINT destsize, int cpin, int cpout, bool * lossy);
#ifndef UNICODE
CString CrossConvertToStringA(LPCSTR src, UINT srclen, int cpin, int cpout, bool * lossy);
#endif

UNICODESET DetermineEncoding(LPBYTE pBuffer, int size, bool * pBom);

} // namespace ucr

bool EqualCodepages(int cp1, int cp2);

#endif // unicoder_h_included

