//	Zinc Application Framework - Z_CSET1.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <z_cset.hpp>
#include <z_string.hpp>
#if !defined(ZAF_UNICODE) && !defined(ZAF_ISO8859_1)
#include "map_def.cpp"
#endif

#define ZAF_CODE_SET_STUB_INFO
#include "gbl_def.cpp"

#if defined(ZAF_MSWINDOWS)
#	include <w_app.hpp>
#endif

ZafCodeSetDataStub::ZafCodeSetDataStub(void):
	ZafI18nData()
{
}

ZafCodeSetDataStub::ZafCodeSetDataStub(const ZafCodeSetDataStub &copy):
	ZafI18nData(copy)
{
}

#if defined(USE_ZAF_PERSISTENCE)
ZafCodeSetDataStub::ZafCodeSetDataStub(const ZafIChar *name, ZafDataPersistence &persist) :
	ZafI18nData(name, persist)
{
}
#endif

ZafCodeSetDataStub::~ZafCodeSetDataStub(void)
{
}

ZafError ZafCodeSetDataStub::SetCodeSetName(const ZafIChar *newCodeSetName)
{
#if defined(USE_ZAF_CODE_SET_DATA)
	// Make sure code set has been initialized once.
	CodeSetAllocate(newCodeSetName);

	// If the code set is correct don't initialize it again.
	if (zafCodeSet && newCodeSetName && *newCodeSetName &&
			!strcmp(newCodeSetName, zafCodeSet->StringID()))
		return (ZAF_ERROR_NONE);

	// Read a new code set from the data manager.
	ZafCodeSetDataStub *newCodeSet = ZAF_NULLP(ZafCodeSetDataStub);
	if (zafDataManager)
	{
		newCodeSet = DynamicPtrCast(zafDataManager->AllocateData(newCodeSetName,
			ZafCodeSetData::className, ZafCodeSetData::classID),
			ZafCodeSetDataStub);
		if (newCodeSet && zafCodeSet)
		{
			if (zafCodeSet && zafCodeSet->Destroyable() && zafCodeSet->NotifyCount() == 0)
				delete zafCodeSet;
			zafCodeSet = newCodeSet;
			// CodeSetAllocate sets ZafApplication to delete zafCodeSet.
			ZafI18nData::SubtractStaticModule(CodeSetFree);
		}
#if defined(USE_ZAF_PERSISTENCE)
		else if (zafDataPersistence)
			zafDataPersistence->SetError(ZAF_ERROR_NONE);
#endif
	}

	// Set the error status.
	if (newCodeSetName && *newCodeSetName && !newCodeSet)
		zafCodeSet->SetError(ZAF_ERROR_INVALID);

	// Return the error status.
	return (newCodeSet ? ZAF_ERROR_NONE : ZAF_ERROR_INVALID);
#else
	return (ZAF_ERROR_NONE);
#endif
}

void ZafCodeSetDataStub::CodeSetAllocate(const ZafIChar *name)
{
#if defined(USE_ZAF_CODE_SET_DATA)
	// Check for initialization.
	if (zafCodeSet)
		return;
	ZafI18nData::AddStaticModule(CodeSetFree);

	// Check for special codes, since ZAF runs natively in unicode or ISO modes.
#	if defined(ZAF_UNICODE)
	static ZafIChar *unicodeName = ZAF_ITEXT("UNICODE");
	if (name && !stricmp(name, unicodeName))
	{
		zafCodeSet = new ZafCodeSetData(ZAF_NULLP(ZafIChar), ZAF_NULLP(ZafIChar));
		zafCodeSet->SetStringID(unicodeName);
		return;
	}
#	elif defined(ZAF_ISO8859_1)
	static ZafIChar *isoName = ZAF_ITEXT("ISO8859-1");
	if (name && !stricmp(name, isoName))
	{
		zafCodeSet = new ZafCodeSetData(ZAF_NULLP(ZafIChar), ZAF_NULLP(ZafIChar));
		zafCodeSet->SetStringID(isoName);
		return;
	}
#	endif

	// Try the zafDataManager.
	ZafError localError = ZAF_ERROR_NONE;
	if (zafDataManager && !zafCodeSet)
	{
		if (name)
			zafCodeSet = DynamicPtrCast(zafDataManager->AllocateData(name, ZafCodeSetData::className, ZafCodeSetData::classID), ZafCodeSetData);

		// Make sure zafCodeSet's destructor isn't called multiple times.
		if (zafCodeSet)
			ZafI18nData::SubtractStaticModule(CodeSetFree);
#if defined(USE_ZAF_PERSISTENCE)
		else if (zafDataPersistence)
		{
			localError = zafDataPersistence->Error();
			zafDataPersistence->SetError(ZAF_ERROR_NONE);
		}
#endif
	}

	// Default to code initialization.
	if (!zafCodeSet)
	{
#	if defined(ZAF_UNICODE)
		zafCodeSet = new ZafCodeSetData(ZAF_NULLP(ZafIChar), ZAF_NULLP(ZafIChar));
		zafCodeSet->SetStringID(unicodeName);
#	elif defined(ZAF_ISO8859_1)
		zafCodeSet = new ZafCodeSetData(ZAF_NULLP(ZafIChar), ZAF_NULLP(ZafIChar));
		zafCodeSet->SetStringID(isoName);
#	else
		zafCodeSet = new ZafCodeSetData(i18nToLocal, localToI18n);
		zafCodeSet->SetStringID(defaultCodeSetName);
#	endif
	}

	// Remap the directory separator based on the current language.
	zafCodeSet->InitializeDirSepStr();

#	if defined(ZAF_UNICODE)
	// Set native unicode support flag.
	zafCodeSet->SetNativeMapping(ZafCodeSetDataStub::OSNativeMapping());
	if (!zafCodeSet->NativeMapping())
	{
		for (ZafIChar *temp = zafCodeSet->dirSepStr; *temp; temp++)
			zafCodeSet->ConvertToZafChar(temp, *temp);
	}
#	else
	for (ZafIChar *temp = zafCodeSet->dirSepStr; *temp; temp++)
		zafCodeSet->ConvertToZafChar(temp, *temp);
#	endif

	// Set/clear the zafCodeSet error.
	zafCodeSet->SetError(localError);
#endif
}

void ZafCodeSetDataStub::CodeSetFree(bool globalRequest)
{
	// Destroy the static locale.
	if (globalRequest && zafCodeSet && zafCodeSet->Destroyable() &&
		zafCodeSet->NotifyCount() == 0)
	{
		delete zafCodeSet;
		zafCodeSet = ZAF_NULLP(ZafCodeSetData);
	}
}

char *ZafConvertToOSString(const ZafIChar *zafString,	char *osString,
	bool allocate)
{
	if (zafCodeSet)
		return (zafCodeSet->ConvertToOSString(zafString, osString, allocate));

	// Seed the osString string.
	static char ZAF_FARDATA mapTextBuffer[256];
	if (!zafString)
		return (ZAF_NULLP(char));

	// Make sure there is a valid buffer.
	int maxLength = (int)(strlen(zafString) + 1);
	if (allocate)
		osString = new char[maxLength * sizeof(ZafIChar)];
	else if (!osString)
	{
		osString = mapTextBuffer;
		maxLength = sizeof(mapTextBuffer);
	}

	for (int i = 0; i < maxLength; i++)
		osString[i] = (char)zafString[i];

	return (osString);
}
#if defined(ZAF_UNICODE)
wchar_t *ZafConvertToOSWString(const ZafIChar *zafString,	wchar_t *osString,
	bool allocate)
{
	if (zafCodeSet)
		return (zafCodeSet->ConvertToOSWString(zafString, osString, allocate));

	// Seed the osString string.
	static wchar_t ZAF_FARDATA mapTextBuffer[256];
	if (!zafString)
		return (ZAF_NULLP(wchar_t));

	// Make sure there is a valid buffer.
	int maxLength = strlen(zafString) + 1;
	if (allocate)
		osString = new wchar_t[maxLength * sizeof(ZafIChar)];
	else if (!osString)
	{
		osString = mapTextBuffer;
		maxLength = sizeof(mapTextBuffer);
	}

	for (int i = 0; i < maxLength; i++)
		osString[i] = zafString[i];

	return (osString);
}

ZafIChar *ZafConvertToZafString(const wchar_t *osString, ZafIChar *zafString,
	bool allocate)
{
	if (zafCodeSet)
		return (zafCodeSet->ConvertToZafString(osString, zafString, allocate));

	static ZafIChar ZAF_FARDATA mapTextBuffer[256];
	if (!osString)
		return (ZAF_NULLP(ZafIChar));

	// Make sure there is a valid buffer.
	int maxLength = strlen(osString) + 1;
	if (allocate)
		zafString = new ZafIChar[maxLength];
	else if (!zafString)
	{
		zafString = mapTextBuffer;
		maxLength = sizeof(mapTextBuffer);
	}

	for (int i = 0; i < maxLength; i++)
		zafString[i] = osString[i];

	return (zafString);
}
#endif

ZafIChar *ZafConvertToZafString(const char *osString, ZafIChar *zafString,
	bool allocate)
{
	if (zafCodeSet)
		return (zafCodeSet->ConvertToZafString(osString, zafString, allocate));

	static ZafIChar ZAF_FARDATA mapTextBuffer[256];
	if (!osString)
		return (ZAF_NULLP(ZafIChar));

	// Make sure there is a valid buffer.
	int maxLength = (int)(strlen(osString) + 1);
	if (allocate)
		zafString = new ZafIChar[maxLength];
	else if (!zafString)
	{
		zafString = mapTextBuffer;
		maxLength = sizeof(mapTextBuffer);
	}

	for (int i = 0; i < maxLength; i++)
		zafString[i] = osString[i];

	return (zafString);
}

ZafIChar *ZafOSDirSepStr(void)
{
	if (zafCodeSet)
		return (zafCodeSet->dirSepStr);

	return (ZAF_DIR_SEP_STR);
}

#if defined(ZAF_UNICODE)
bool ZafCodeSetDataStub::OSNativeMapping(void)
{
#if defined(ZAF_MSWINDOWS)
	return (!ZafMSWindowsApp::convertText);
#else
	return (false);
#endif
}
#endif
