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

#include <z_idata.hpp>
#include <z_loc.hpp>
#include <z_lang.hpp>
#include <z_cset.hpp>
#include <z_string.hpp>
#define ZAF_I18N_DATA_INFO
#include "gbl_def.cpp"
#if defined(ZAF_MACINTOSH)
#	include <Packages.h>
#endif

// ----- ZafI18nData --------------------------------------------------------

ZafI18nData::ZafI18nData(void) :
	ZafData()
{
}

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

ZafI18nData::~ZafI18nData(void)
{
}

bool ZafI18nData::AddStaticModule(ZafFreeModule freeModule, ZafAllocateModule allocateModule, ZafClassID category)
{
	// Make sure it is a valid request.
	if (!allocateModule && !freeModule)
		return (false);

	// Check the array.
	int offset = 0;
	if (staticModule)
	{
		// Find the last item.
		while (staticModule[offset].category != ID_END)
			if (staticModule[offset].allocateModule == allocateModule &&
				staticModule[offset].freeModule == freeModule)
				return (true);
			else
				offset++;
		// Reallocate the array.
		if (((offset + 1) % ZAF_DYNAMIC_ARRAY_INCREMENT) == 0)
		{
			ZafStaticModule *tempArray = staticModule;
			staticModule = new ZafStaticModule[offset + ZAF_DYNAMIC_ARRAY_INCREMENT + 1];
			memcpy(staticModule, tempArray, offset * sizeof(ZafStaticModule));
			delete []tempArray;
		}
	}
	else
		staticModule = new ZafStaticModule[ZAF_DYNAMIC_ARRAY_INCREMENT];

	// Reset the array.
	staticModule[offset+1].allocateModule = ZAF_NULLF(ZafAllocateModule);
	staticModule[offset+1].freeModule = ZAF_NULLF(ZafFreeModule);
	staticModule[offset+1].category = ID_END;

	staticModule[offset].allocateModule = allocateModule;
	staticModule[offset].freeModule = freeModule;
	staticModule[offset].category = category;

	return (true);
}

void ZafI18nData::I18nAllocate(const ZafIChar *newI18nName)
{
	// Check for initialization.
	if (zafCodeSet && zafLanguageManager && zafLocale)
		return;

	// If no new name is specified, the initialization of language, locale,
	// and codeset defaults to the compiled values.
	if (!newI18nName)
		newI18nName = OSI18nName();

	if (newI18nName)
		SetI18nName(newI18nName);
	else
	{
		ZafCodeSetDataStub::CodeSetAllocate();
		ZafLanguageManager::LanguageAllocate();
		ZafLocaleData::LocaleAllocate();
	}
}

void ZafI18nData::I18nFree(bool globalRequest)
{
	if (globalRequest)
	{
		// Free static memory modules (these modules need the zafDisplay pointer).
		if (staticModule)
		{
			for (int i = 0; staticModule[i].category != ID_END; i++)
				(*staticModule[i].freeModule)(true);
			delete []staticModule;
			staticModule = ZAF_NULLP(ZafStaticModule);
		}
	}
	else
	{
		// Reset the appropriate information.
		if (staticModule)
		{
			for (int i = 0; staticModule[i].category != ID_END; i++)
				if (staticModule[i].category == ZafLanguageData::classID &&
					staticModule[i].allocateModule)
				{
					(*staticModule[i].freeModule)(true);
					(*staticModule[i].allocateModule)();
				}
		}
	}
}

const ZafIChar *ZafI18nData::I18nName(void)
{
	// Format for i18nName is language[_locale[.codeset]].
	strcpy(i18nName, ZafLanguageManager::LanguageName() ? ZafLanguageManager::LanguageName() : ZafLanguageManager::blankString);
	if (ZafLocaleData::LocaleName())
	{
		strcat(i18nName, ZAF_ITEXT("_"));
		strcat(i18nName, ZafLocaleData::LocaleName());
	}
	if (ZafCodeSetDataStub::CodeSetName())
	{
		strcat(i18nName, ZAF_ITEXT("."));
		strcat(i18nName, ZafCodeSetDataStub::CodeSetName());
	}

	// Return the i18n name.
	return (i18nName);
}

bool ZafI18nData::IsA(ZafClassID compareID) const
{
	return ((compareID == classID) ? true : ZafData::IsA(compareID));
}

bool ZafI18nData::IsA(ZafClassName compareName) const
{
	return (!strcmp(compareName, className) ? true : ZafData::IsA(compareName));
}

const ZafIChar *ZafI18nData::ResetI18n(const ZafIChar *newName)
{
	// Check to make sure that the information is not already up-to-date.
	const ZafIChar *oldName = I18nName();
	const ZafIChar *osName = OSI18nName();
	if (!newName && !osName)
		return (oldName);

	// Clean up the data manager so we get new information.
	if (zafDataManager)
	{
		zafDataManager->Subtract(zafCodeSet);
		zafDataManager->Subtract(zafLanguageManager);
		zafDataManager->Subtract(zafLocale);

		// Free the internationalization information.
		ZafCodeSetDataStub::CodeSetFree(true);
//		ZafLanguageManager::LanguageFree(true);
		ZafLocaleData::LocaleFree(true);
	}

	// Allocate must be called before free so that the items that rely on 
	// the new settings can initialize properly.
	I18nAllocate(newName ? newName : osName);
	I18nFree(false);

	// Return the current i18n information.
	return (I18nName());
}

bool ZafI18nData::SubtractStaticModule(ZafFreeModule freeModule, ZafAllocateModule allocateModule)
{
	// Make sure it is a valid request.
	if (!staticModule || (!allocateModule && !freeModule))
		return (false);

	// Find the matching module.
	int offset = -1, count = 0;
	while (staticModule[count].category != ID_END)
	{
		if (staticModule[count].allocateModule == allocateModule &&
			staticModule[count].freeModule == freeModule)
			offset = count;
		count++;
	}

	// Reset the array.
	if (offset != -1)
	{
		memmove(&staticModule[offset], &staticModule[offset+1], (count - offset) * sizeof(ZafStaticModule));
		return (true);
	}
	return (false);
}

struct ZafLanguageMap1
{
	ZafIChar *osLanguageName;
	ZafIChar *zafLanguageName;
} languageMap1[] =
{
#if defined(__hpux)
	{ ZAF_ITEXT("american"),		ZAF_ITEXT("en") },
	{ ZAF_ITEXT("arabic"),			ZAF_ITEXT("ar") },
	{ ZAF_ITEXT("arabic-w"),		ZAF_ITEXT("ar") },
	{ ZAF_ITEXT("bulgarian"),		ZAF_ITEXT("bg") },
	{ ZAF_ITEXT("c-french"),		ZAF_ITEXT("fr") },
	{ ZAF_ITEXT("chinese-s"),		ZAF_ITEXT("zh") },
	{ ZAF_ITEXT("chinese-t"),		ZAF_ITEXT("zh") },
	{ ZAF_ITEXT("czech"),			ZAF_ITEXT("cs") },
	{ ZAF_ITEXT("danish"),			ZAF_ITEXT("da") },
	{ ZAF_ITEXT("dutch"),			ZAF_ITEXT("nl") },
	{ ZAF_ITEXT("english"),			ZAF_ITEXT("en") },
	{ ZAF_ITEXT("finnish"),			ZAF_ITEXT("fi") },
	{ ZAF_ITEXT("french"),			ZAF_ITEXT("fr") },
	{ ZAF_ITEXT("german"),			ZAF_ITEXT("de") },
	{ ZAF_ITEXT("greek"),			ZAF_ITEXT("el") },
	{ ZAF_ITEXT("hebrew"),			ZAF_ITEXT("iw") },
	{ ZAF_ITEXT("hungarian"),		ZAF_ITEXT("hu") },
	{ ZAF_ITEXT("icelandic"),		ZAF_ITEXT("is") },
	{ ZAF_ITEXT("italian"),			ZAF_ITEXT("it") },
	{ ZAF_ITEXT("japanese"),		ZAF_ITEXT("ja") },
	{ ZAF_ITEXT("katakana"),		ZAF_ITEXT("ja") },
	{ ZAF_ITEXT("korean"),			ZAF_ITEXT("ko") },
	{ ZAF_ITEXT("norwegian"),		ZAF_ITEXT("no") },
	{ ZAF_ITEXT("polish"),			ZAF_ITEXT("pl") },
	{ ZAF_ITEXT("portuguese"),		ZAF_ITEXT("pt") },
	{ ZAF_ITEXT("rumanian"),		ZAF_ITEXT("ro") },
	{ ZAF_ITEXT("russian"),			ZAF_ITEXT("ru") },
	{ ZAF_ITEXT("serbocroatian"),	ZAF_ITEXT("sh") },
	{ ZAF_ITEXT("slovene"),			ZAF_ITEXT("sl") },
	{ ZAF_ITEXT("spanish"),			ZAF_ITEXT("es") },
	{ ZAF_ITEXT("swedish"),			ZAF_ITEXT("sv") },
	{ ZAF_ITEXT("thai"),			ZAF_ITEXT("th") },
	{ ZAF_ITEXT("turkish"),			ZAF_ITEXT("tr") },
#elif defined(ZAF_MSWINDOWS)
#	if defined(ZAF_WIN32)
	{ ZAF_ITEXT("0x01"),			ZAF_ITEXT("ar") },	// LANG_ARABIC
	{ ZAF_ITEXT("0x02"),			ZAF_ITEXT("bg") },	// LANG_BULGARIAN
	{ ZAF_ITEXT("0x03"),			ZAF_ITEXT("ca") },	// LANG_CATALAN
	{ ZAF_ITEXT("0x04"),			ZAF_ITEXT("zh") },	// LANG_CHINESE
	{ ZAF_ITEXT("0x05"),			ZAF_ITEXT("cs") },	// LANG_CZECH
	{ ZAF_ITEXT("0x06"),			ZAF_ITEXT("da") },	// LANG_DANISH
	{ ZAF_ITEXT("0x07"),			ZAF_ITEXT("de") },	// LANG_GERMAN
	{ ZAF_ITEXT("0x08"),			ZAF_ITEXT("el") },	// LANG_GREEK
	{ ZAF_ITEXT("0x09"),			ZAF_ITEXT("en") },	// LANG_ENGLISH
	{ ZAF_ITEXT("0x0a"),			ZAF_ITEXT("es") },	// LANG_SPANISH
	{ ZAF_ITEXT("0x0b"),			ZAF_ITEXT("fi") },	// LANG_FINNISH
	{ ZAF_ITEXT("0x0c"),			ZAF_ITEXT("fr") },	// LANG_FRENCH
	{ ZAF_ITEXT("0x0d"),			ZAF_ITEXT("iw") },	// LANG_HEBREW
	{ ZAF_ITEXT("0x0e"),			ZAF_ITEXT("hu") },	// LANG_HUNGARIAN
	{ ZAF_ITEXT("0x0f"),			ZAF_ITEXT("is") },	// LANG_ICELANDIC
	{ ZAF_ITEXT("0x10"),			ZAF_ITEXT("it") },	// LANG_ITALIAN
	{ ZAF_ITEXT("0x11"),			ZAF_ITEXT("ja") },	// LANG_JAPANESE
	{ ZAF_ITEXT("0x12"),			ZAF_ITEXT("ko") },	// LANG_KOREAN
	{ ZAF_ITEXT("0x13"),			ZAF_ITEXT("nl") },	// LANG_DUTCH
	{ ZAF_ITEXT("0x14"),			ZAF_ITEXT("no") },	// LANG_NORWEGIAN
	{ ZAF_ITEXT("0x15"),			ZAF_ITEXT("pl") },	// LANG_POLISH
	{ ZAF_ITEXT("0x16"),			ZAF_ITEXT("pt") },	// LANG_PORTUGUESE
	{ ZAF_ITEXT("0x17"),			ZAF_ITEXT("rm") },	// LANG_RHAETO_ROMAN
	{ ZAF_ITEXT("0x18"),			ZAF_ITEXT("ro") },	// LANG_ROMANIAN
	{ ZAF_ITEXT("0x19"),			ZAF_ITEXT("ru") },	// LANG_RUSSIAN
	{ ZAF_ITEXT("0x1a"),			ZAF_ITEXT("sh") },	// LANG_SERBO_CROATIAN
	{ ZAF_ITEXT("0x1b"),			ZAF_ITEXT("sk") },	// LANG_SLOVAK
	{ ZAF_ITEXT("0x1c"),			ZAF_ITEXT("sq") },	// LANG_ALBANIAN
	{ ZAF_ITEXT("0x1d"),			ZAF_ITEXT("sv") },	// LANG_SWEDISH
	{ ZAF_ITEXT("0x1e"),			ZAF_ITEXT("th") },	// LANG_THAI
	{ ZAF_ITEXT("0x1f"),			ZAF_ITEXT("tr") },	// LANG_TURKISH
	{ ZAF_ITEXT("0x20"),			ZAF_ITEXT("ur") },	// LANG_URDU
//	{ ZAF_ITEXT("0x21"),			ZAF_ITEXT("") },	// LANG_BAHASA
#	endif
	// This must be included for Win32s
	{ ZAF_ITEXT("cat"), 			ZAF_ITEXT("ca") },	// Catalan
	{ ZAF_ITEXT("chs"), 			ZAF_ITEXT("zh") },	// China PROC
	{ ZAF_ITEXT("cht"), 			ZAF_ITEXT("zh") },	// China ROC
	{ ZAF_ITEXT("csy"), 			ZAF_ITEXT("cs") },	// Czech Republic.
	{ ZAF_ITEXT("dan"), 			ZAF_ITEXT("da") },	// Denmark.
	{ ZAF_ITEXT("dea"), 			ZAF_ITEXT("de") },	// Austria.
	{ ZAF_ITEXT("des"), 			ZAF_ITEXT("de") },	// German Switzerland.
	{ ZAF_ITEXT("deu"), 			ZAF_ITEXT("de") },	// Germany.
	{ ZAF_ITEXT("ell"), 			ZAF_ITEXT("el") },	// Greece.
	{ ZAF_ITEXT("eng"), 			ZAF_ITEXT("en") },	// England.
	{ ZAF_ITEXT("eni"), 			ZAF_ITEXT("en") },	// Ireland.
	{ ZAF_ITEXT("ena"), 			ZAF_ITEXT("en") },	// Australia.
	{ ZAF_ITEXT("enc"), 			ZAF_ITEXT("en") },	// English Canada.
	{ ZAF_ITEXT("enu"), 			ZAF_ITEXT("en") },	// United States.
	{ ZAF_ITEXT("enz"), 			ZAF_ITEXT("en") },	// New Zealand.
	{ ZAF_ITEXT("esm"), 			ZAF_ITEXT("es") },	// Mexico.
	{ ZAF_ITEXT("esn"), 			ZAF_ITEXT("es") },	// Modern Spain.
	{ ZAF_ITEXT("esp"), 			ZAF_ITEXT("es") },	// Traditional Spain.
	{ ZAF_ITEXT("ess"), 			ZAF_ITEXT("es") },	// Argentina.
	{ ZAF_ITEXT("fin"), 			ZAF_ITEXT("fi") },	// Finland.
	{ ZAF_ITEXT("fra"), 			ZAF_ITEXT("fr") },	// France.
	{ ZAF_ITEXT("frb"), 			ZAF_ITEXT("fr") },	// French Belgium.
	{ ZAF_ITEXT("frc"), 			ZAF_ITEXT("fr") },	// French Canada.
	{ ZAF_ITEXT("frs"), 			ZAF_ITEXT("fr") },	// French Switzerland.
	{ ZAF_ITEXT("hun"), 			ZAF_ITEXT("hu") },	// Hungary.
	{ ZAF_ITEXT("isl"), 			ZAF_ITEXT("is") },	// Iceland.
	{ ZAF_ITEXT("ita"), 			ZAF_ITEXT("it") },	// Italy.
	{ ZAF_ITEXT("its"), 			ZAF_ITEXT("it") },	// Italian Switzerland.
	{ ZAF_ITEXT("jpn"), 			ZAF_ITEXT("ja") },	// Japan.
	{ ZAF_ITEXT("kor"), 			ZAF_ITEXT("ko") },	// Japan.
	{ ZAF_ITEXT("nlb"), 			ZAF_ITEXT("nl") },	// Dutch Belgium.
	{ ZAF_ITEXT("nld"), 			ZAF_ITEXT("nl") },	// Netherlands.
	{ ZAF_ITEXT("nor"), 			ZAF_ITEXT("no") },	// Norway (Bokmal).
	{ ZAF_ITEXT("non"), 			ZAF_ITEXT("no") },	// Norway (Nynorsk).
	{ ZAF_ITEXT("plk"), 			ZAF_ITEXT("pl") },	// Poland.
	{ ZAF_ITEXT("ptb"), 			ZAF_ITEXT("pt") },	// Brazil.
	{ ZAF_ITEXT("ptg"), 			ZAF_ITEXT("pt") },	// Portugal.
	{ ZAF_ITEXT("rus"), 			ZAF_ITEXT("ru") },	// Russia.
	{ ZAF_ITEXT("sky"), 			ZAF_ITEXT("sk") },	// Slovak Republic.
	{ ZAF_ITEXT("sve"), 			ZAF_ITEXT("sv") },	// Sweden.
	{ ZAF_ITEXT("trk"), 			ZAF_ITEXT("tr") },	// Turkey.
#endif
	{  ZAF_NULLP(ZafIChar),			ZAF_NULLP(ZafIChar) }
};

const ZafIChar *ZafI18nData::OSLanguageToZafLanguage(const ZafIChar *osLanguage)
{
	// Try to find a matching name.
	ZafLanguageMap1 *map = languageMap1;
	for ( ; map->osLanguageName; map++)
		if (!strcmp(osLanguage, map->osLanguageName))
			break;
	return (map->zafLanguageName);
}

struct ZafLanguageMap2
{
	ZafIChar *localeName;
	ZafIChar *languageName;
} languageMap2[] =
{
	{ ZAF_ITEXT("AR"), ZAF_ITEXT("es") },	// Argentina
	{ ZAF_ITEXT("AU"), ZAF_ITEXT("en") },	// Australia
	{ ZAF_ITEXT("BE"), ZAF_ITEXT("fr") },	// Belgium
	{ ZAF_ITEXT("BR"), ZAF_ITEXT("pt") },	// Brazil
	{ ZAF_ITEXT("CA"), ZAF_ITEXT("fr") },	// Canada
	{ ZAF_ITEXT("CH"), ZAF_ITEXT("de") },	// Switzerland
	{ ZAF_ITEXT("CN"), ZAF_ITEXT("zh") },	// PROC
	{ ZAF_ITEXT("CY"), ZAF_ITEXT("el") },	// Cyprus
	{ ZAF_ITEXT("CZ"), ZAF_ITEXT("cs") },	// Czechoslavakia
	{ ZAF_ITEXT("DE"), ZAF_ITEXT("de") },	// Germany
	{ ZAF_ITEXT("DK"), ZAF_ITEXT("da") },	// Denmark
	{ ZAF_ITEXT("EE"), ZAF_ITEXT("et") },	// Estonia
	{ ZAF_ITEXT("ES"), ZAF_ITEXT("es") },	// Spain
	{ ZAF_ITEXT("FI"), ZAF_ITEXT("fi") },	// Finland
	{ ZAF_ITEXT("FO"), ZAF_ITEXT("fo") },	// Faeroe Islands
	{ ZAF_ITEXT("FR"), ZAF_ITEXT("fr") },	// France
	{ ZAF_ITEXT("GB"), ZAF_ITEXT("en") },	// United Kingdom
	{ ZAF_ITEXT("GR"), ZAF_ITEXT("el") },	// Greece
	{ ZAF_ITEXT("HU"), ZAF_ITEXT("hu") },	// Hungary
	{ ZAF_ITEXT("IE"), ZAF_ITEXT("ga") },	// Ireland
	{ ZAF_ITEXT("IL"), ZAF_ITEXT("iw") },	// Israel
	{ ZAF_ITEXT("IN"), ZAF_ITEXT("hi") },	// India
	{ ZAF_ITEXT("IR"), ZAF_ITEXT("fa") },	// Iran
	{ ZAF_ITEXT("IS"), ZAF_ITEXT("is") },	// Iceland
	{ ZAF_ITEXT("IT"), ZAF_ITEXT("it") },	// Italy
	{ ZAF_ITEXT("JP"), ZAF_ITEXT("ja") },	// Japan
	{ ZAF_ITEXT("KR"), ZAF_ITEXT("ko") },	// Korea
	{ ZAF_ITEXT("LT"), ZAF_ITEXT("lt") },	// Lithuania
	{ ZAF_ITEXT("LV"), ZAF_ITEXT("lv") },	// Latvia
	{ ZAF_ITEXT("MT"), ZAF_ITEXT("mt") },	// Malta
	{ ZAF_ITEXT("NL"), ZAF_ITEXT("nl") },	// Netherlands
	{ ZAF_ITEXT("NO"), ZAF_ITEXT("no") },	// Norway
	{ ZAF_ITEXT("PK"), ZAF_ITEXT("ar") },	// Pakistan
	{ ZAF_ITEXT("PL"), ZAF_ITEXT("pl") },	// Poland
	{ ZAF_ITEXT("PT"), ZAF_ITEXT("pt") },	// Portugal
	{ ZAF_ITEXT("RU"), ZAF_ITEXT("ru") },	// Russia
	{ ZAF_ITEXT("SA"), ZAF_ITEXT("ar") },	// Saudi Arabia
	{ ZAF_ITEXT("SE"), ZAF_ITEXT("sv") },	// Sweden
	{ ZAF_ITEXT("TH"), ZAF_ITEXT("th") },	// Thailand
	{ ZAF_ITEXT("TR"), ZAF_ITEXT("tr") },	// Turkey
	{ ZAF_ITEXT("TW"), ZAF_ITEXT("zh") },	// ROC
	{ ZAF_ITEXT("US"), ZAF_ITEXT("en") },	// United States
	{ ZAF_ITEXT("YU"), ZAF_ITEXT("sh") },	// Yugoslavia
	{ ZAF_NULLP(ZafIChar), ZAF_ITEXT("") }
};

const ZafIChar *ZafI18nData::ZafLocaleToZafLanguage(const ZafIChar *locale)
{
	// Try to find a matching name.
	ZafLanguageMap2 *map = languageMap2;
	for ( ; map->localeName; map++)
		if (!strcmp(locale, map->localeName))
			break;
	return (map->languageName);
}

struct ZafCountryCodeMap
{
	int osCountryCode;
	ZafIChar *defaultLocale;
} countryCodeMap[] =
{
#if defined(ZAF_MACINTOSH)
	{ verUS,					ZAF_ITEXT("US") },
	{ verFrance,			ZAF_ITEXT("FR") },
	{ verBritain,			ZAF_ITEXT("GB") },
	{ verGermany,			ZAF_ITEXT("DE") },
	{ verItaly,				ZAF_ITEXT("IT") },
	{ verNetherlands,		ZAF_ITEXT("NL") },
	{ verFrBelgiumLux,	ZAF_ITEXT("BE") },
	{ verSweden,			ZAF_ITEXT("SE") },
	{ verSpain,				ZAF_ITEXT("ES") },
	{ verDenmark,			ZAF_ITEXT("DK") },
	{ verPortugal,			ZAF_ITEXT("PT") },
	{ verFrCanada,			ZAF_ITEXT("CA") },
	{ verNorway,			ZAF_ITEXT("NO") },
	{ verIsrael,			ZAF_ITEXT("IL") },
	{ verJapan,				ZAF_ITEXT("JP") },
	{ verAustralia,		ZAF_ITEXT("AU") },
	{ verArabic,			ZAF_ITEXT("SA") },
	{ verFinland,			ZAF_ITEXT("FI") },
	{ verFrSwiss,			ZAF_ITEXT("CH") },
	{ verGrSwiss,			ZAF_ITEXT("CH") },
	{ verGreece,			ZAF_ITEXT("GR") },
	{ verIceland,			ZAF_ITEXT("IS") },
	{ verMalta,				ZAF_ITEXT("MT") },
	{ verCyprus,			ZAF_ITEXT("CY") },
	{ verTurkey,			ZAF_ITEXT("TR") },
	{ verYugoCroatian,	ZAF_ITEXT("YU") },
	{ verIndiaHindi,		ZAF_ITEXT("IN") },
	{ verPakistan,			ZAF_ITEXT("PK") },
	{ verLithuania,		ZAF_ITEXT("LT") },
	{ verPoland,			ZAF_ITEXT("PL") },
	{ verHungary,			ZAF_ITEXT("HU") },
	{ verEstonia,			ZAF_ITEXT("EE") },
	{ verLatvia,			ZAF_ITEXT("LV") },
	{ verLapland,			ZAF_ITEXT("NO") },
	{ verFaeroeIsl,		ZAF_ITEXT("FO") },
	{ verIran,				ZAF_ITEXT("IR") },
	{ verRussia,			ZAF_ITEXT("RU") },
	{ verIreland,			ZAF_ITEXT("IE") },
	{ verKorea,				ZAF_ITEXT("KR") },
	{ verChina,				ZAF_ITEXT("CN") },
	{ verTaiwan,			ZAF_ITEXT("TW") },
	{ verThailand,			ZAF_ITEXT("TH") },
#else
	{   1, 					ZAF_ITEXT("US") },	// United States
	{   2, 					ZAF_ITEXT("CA") },	// Canada
	{  31, 					ZAF_ITEXT("NL") },	// Netherlands
	{  32, 					ZAF_ITEXT("BE") },	// Belgium
	{  33, 					ZAF_ITEXT("FR") },	// France
	{  34, 					ZAF_ITEXT("ES") },	// Spain
	{  36, 					ZAF_ITEXT("HU") },	// Hungary
	{  38, 					ZAF_ITEXT("YU") },	// Yugoslavia
	{  39, 					ZAF_ITEXT("IT") },	// Italy
	{  41, 					ZAF_ITEXT("CH") },	// Switzerland
	{  42, 					ZAF_ITEXT("CZ") },	// Czechoslavakia
	{  43, 					ZAF_ITEXT("AT") },	// Austria
	{  44, 					ZAF_ITEXT("GB") },	// United Kingdom
	{  45, 					ZAF_ITEXT("DK") },	// Denmark
	{  46, 					ZAF_ITEXT("SE") },	// Sweden
	{  47, 					ZAF_ITEXT("NO") },	// Norway
	{  48, 					ZAF_ITEXT("PL") },	// Poland
	{  49, 					ZAF_ITEXT("DE") },	// Germany
	{  54, 					ZAF_ITEXT("AR") },	// Argentina
	{  55, 					ZAF_ITEXT("BR") },	// Brazil
	{  61, 					ZAF_ITEXT("AU") },	// Australia
	{  81, 					ZAF_ITEXT("JP") },	// Japan
	{  82, 					ZAF_ITEXT("KR") },	// Korea
	{  86, 					ZAF_ITEXT("CN") },	// PROC
	{  88, 					ZAF_ITEXT("TW") },	// ROC
	{  90, 					ZAF_ITEXT("TR") },	// Turkey
	{ 351, 					ZAF_ITEXT("PT") },	// Portugal
	{ 354, 					ZAF_ITEXT("IS") },	// Iceland
	{ 358, 					ZAF_ITEXT("FI") },	// Finland
	{ 785, 					ZAF_ITEXT("SA") },	// Saudi Arabia
	{ 886, 					ZAF_ITEXT("TW") },	// ROC
	{ 972, 					ZAF_ITEXT("IL") },	// Israel
#endif
	{  0,  					ZAF_ITEXT("") }
};

const ZafIChar *ZafI18nData::CountryCodeToZafLocale(int countryCode)
{
	// Try to find a matching entry.
	ZafCountryCodeMap *map = countryCodeMap;
	for ( ; map->defaultLocale; map++)
		if (countryCode == map->osCountryCode)
			break;
	return (map->defaultLocale);
}

struct LocaleMap
{
	ZafIChar *languageName;
	ZafIChar *defaultLocale;
} localeMap[] =
{
#if defined(__hpux)
	{ ZAF_ITEXT("ar"),		ZAF_ITEXT("SA") },
	{ ZAF_ITEXT("bg"),		ZAF_ITEXT("BG") },
	{ ZAF_ITEXT("cs"),		ZAF_ITEXT("CZ") },
	{ ZAF_ITEXT("da"),		ZAF_ITEXT("DK") },
	{ ZAF_ITEXT("de"),		ZAF_ITEXT("DE") },
	{ ZAF_ITEXT("el"),		ZAF_ITEXT("GR") },
	{ ZAF_ITEXT("en"),		ZAF_ITEXT("US") },
	{ ZAF_ITEXT("es"),		ZAF_ITEXT("ES") },
	{ ZAF_ITEXT("fi"),		ZAF_ITEXT("FI") },
	{ ZAF_ITEXT("fr"),		ZAF_ITEXT("FR") },
	{ ZAF_ITEXT("hu"),		ZAF_ITEXT("HU") },
	{ ZAF_ITEXT("is"),		ZAF_ITEXT("IS") },
	{ ZAF_ITEXT("it"),		ZAF_ITEXT("IT") },
	{ ZAF_ITEXT("iw"),		ZAF_ITEXT("IL") },
	{ ZAF_ITEXT("ja"),		ZAF_ITEXT("JP") },
	{ ZAF_ITEXT("ko"),		ZAF_ITEXT("KR") },
	{ ZAF_ITEXT("nl"),		ZAF_ITEXT("NL") },
	{ ZAF_ITEXT("no"),		ZAF_ITEXT("NO") },
	{ ZAF_ITEXT("pl"),		ZAF_ITEXT("PL") },
	{ ZAF_ITEXT("pt"),		ZAF_ITEXT("PT") },
	{ ZAF_ITEXT("ro"),		ZAF_ITEXT("RO") },
	{ ZAF_ITEXT("ru"),		ZAF_ITEXT("RU") },
	{ ZAF_ITEXT("sh"),		ZAF_ITEXT("YU") },
	{ ZAF_ITEXT("sl"),		ZAF_ITEXT("SI") },
	{ ZAF_ITEXT("sv"),		ZAF_ITEXT("SE") },
	{ ZAF_ITEXT("th"),		ZAF_ITEXT("TH") },
	{ ZAF_ITEXT("tr"),		ZAF_ITEXT("TR") },
	{ ZAF_ITEXT("zh"),		ZAF_ITEXT("CN") },
#endif
	{ ZAF_NULLP(ZafIChar),	ZAF_ITEXT("") }
};

const ZafIChar *ZafI18nData::ZafLanguageToZafLocale(const ZafIChar *language)
{
	// Try to find a matching entry.
	LocaleMap *map = localeMap;
	for ( ; map->languageName; map++)
		if (!strcmp(language, map->languageName))
			break;
	return (map->defaultLocale);
}

ZafError ZafI18nData::SetI18nName(const ZafIChar *newLanguageName,
	const ZafIChar *newLocaleName, const ZafIChar *newCodeSetName)
{
	// Recompute the i18n components.
#if defined(USE_ZAF_PERSISTENCE)
	if (zafDataPersistence)
		zafDataPersistence->SetError(ZAF_ERROR_NONE);
#endif

	ZafCodeSetDataStub::SetCodeSetName(newCodeSetName);
	ZafLanguageManager::SetLanguageName(newLanguageName);
	ZafLocaleData::SetLocaleName(newLocaleName);

	// Return the i18n status.
	if (zafLanguageManager->Error())
		return (zafLanguageManager->Error());
	else if (zafLocale->Error())
		return (zafLocale->Error());
	return (zafCodeSet ? zafCodeSet->Error() : ZAF_ERROR_NONE);
}

ZafError ZafI18nData::SetI18nName(const ZafIChar *newI18nName)
{
	// Check to see if the I18n information is already up-to-date.
	const ZafIChar *oldName = I18nName();
	if (!strcmp(newI18nName, oldName) && *newI18nName && zafCodeSet &&
	 zafLocale)
		return (ZAF_ERROR_NONE);

	strcpy(i18nName, newI18nName);

	// Parse i18nName in the form language[_locale[.codeset]].
	ZafIChar *langPtr = i18nName;
	ZafIChar *localePtr = strchr(i18nName, '_');
	ZafIChar *codeSetPtr = strchr(i18nName, '.');
	if (localePtr)
	{
		localePtr[0] = '\0';
		localePtr = &localePtr[1];
	}
	if (codeSetPtr)
	{
		codeSetPtr[0] = '\0';
		codeSetPtr = &codeSetPtr[1];
	}

	// Return the i18n status.
	return (SetI18nName(langPtr, localePtr, codeSetPtr));
}

#if defined(USE_ZAF_PERSISTENCE)
// ----- Persistent functions -----------------------------------------------
ZafI18nData::ZafI18nData(const ZafIChar *name, ZafDataPersistence &persist):
	ZafData(name, persist.PushLevel(className, classID, ZAF_PERSIST_ROOT_DIRECTORY))
{
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

void ZafI18nData::Write(ZafDataPersistence &persist)
{
	// Write the object.
	ZafData::Write(persist.PushLevel(className, classID, ZAF_PERSIST_ROOT_DIRECTORY));
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}
#endif
