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

#include <z_cset.hpp>
#include <z_icon.hpp>
#include <z_lang.hpp>
#include <z_string.hpp> // For strcmp().
#define ZAF_ICON_DATA_INFO
#include "gbl_def.cpp"

#if defined(ZAF_MSWINDOWS)
#	include <w_app.hpp>
#elif defined(ZAF_MACINTOSH)
#	include <Icons.h>
#	include <ToolUtils.h>
#endif

// ----- ZafIconStruct ------------------------------------------------------

ZafIconStruct::ZafIconStruct(void)
{
	width = height = 0, array = ZAF_NULLP(ZafLogicalColor), staticArray = staticHandle = false;
#	if defined(ZAF_MSWINDOWS)
	handle = 0;
#	elif defined(ZAF_MOTIF)
	handle = mask = 0;
#	elif defined(ZAF_MACINTOSH)
	colorBitmap = ZAF_NULLH(PixMapHandle);
	monoBitmap = mask = ZAF_NULLH(BitMapHandle);
	handle = ZAF_NULLH(Handle);
#	elif defined(ZAF_INDEPENDENT)
	handle = mask = 0;
#	endif
}

ZafIconStruct::ZafIconStruct(const ZafImageStruct &data)
{
	width = data.width, height = data.height, array = data.array, staticHandle = false, staticArray = data.staticArray;
#	if defined(ZAF_MSWINDOWS)
	handle = 0;
#	elif defined(ZAF_MOTIF)
	handle = mask = 0;
#	elif defined(ZAF_MACINTOSH)
	colorBitmap = ZAF_NULLH(PixMapHandle);
	monoBitmap = mask = ZAF_NULLH(BitMapHandle);
	handle = ZAF_NULLH(Handle);
#	elif defined(ZAF_INDEPENDENT)
	handle = mask = 0;
#	endif
}

ZafIconStruct::ZafIconStruct(int tWidth, int tHeight, ZafLogicalColor *tArray, bool tStaticArray)
{
	width = tWidth, height = tHeight, array = tArray, staticHandle = false, staticArray = tStaticArray;
#	if defined(ZAF_MSWINDOWS)
	handle = 0;
#	elif defined(ZAF_MOTIF)
	handle = mask = 0;
#	elif defined(ZAF_MACINTOSH)
	colorBitmap = ZAF_NULLH(PixMapHandle);
	monoBitmap = mask = ZAF_NULLH(BitMapHandle);
	handle = ZAF_NULLH(Handle);
#	elif defined(ZAF_INDEPENDENT)
	handle = mask = 0;
#	endif
}

// ----- ZafIconData --------------------------------------------------------

ZafIconData::ZafIconData(const ZafImageStruct &data) :
	ZafImageData()
{
	// Initialize the image information.
	array = ZAF_NULLP(ZafLogicalColor);
	SetImage(*this, data);
#if !defined(ZAF_TEXT_MODE)
	ZafDisplay::InitializeOSIcon(*this);
#endif
}

// OS specific constructor to create the icon from an OS resource.
#if defined(ZAF_MOTIF) || defined(ZAF_INDEPENDENT)
ZafIconData::ZafIconData(const ZafIChar *, int) :
	ZafImageData()
#else
ZafIconData::ZafIconData(const ZafIChar *resourceName, int resourceID) :
	ZafImageData()
#endif
{
	array = ZAF_NULLP(ZafLogicalColor);

#if defined(ZAF_MSWINDOWS)
	char *osResourceName = 0;
	if (resourceName)
		osResourceName = zafCodeSet->ConvertToOSString(resourceName);
#	if defined(ZAF_WIN32)
	if (osResourceName)
		handle = LoadIconA(ZafMSWindowsApp::hInstance, osResourceName);
	else
		handle = LoadIconA(ZafMSWindowsApp::hInstance, MAKEINTRESOURCEA(resourceID));
#	else
	if (osResourceName)
		handle = LoadIcon(ZafMSWindowsApp::hInstance, osResourceName);
	else
		handle = LoadIcon(ZafMSWindowsApp::hInstance, MAKEINTRESOURCE(resourceID));
#	endif
	delete []osResourceName;
#elif defined(ZAF_MOTIF)
	handle = mask = 0;
#elif defined(ZAF_MACINTOSH)
	colorBitmap = ZAF_NULLH(PixMapHandle);
	monoBitmap = mask = ZAF_NULLH(BitMapHandle);
	handle = ZAF_NULLH(Handle);

	// Try to load the icon from the resource forks that are open.
	if (resourceID != -1)
	{
		// GetIcon() searches all open resource files.
		// Normally, this is: Application, then System file.
		handle = GetIcon((short)resourceID);
	}
	if (!handle && resourceName)
	{
		// GetNamedResource() does a case-insensitive search in all open resource files.
		// Normally, this is: Application, then System file.
		char buff[256];
#	if defined(ZAF_UNICODE) || defined(ZAF_ISO8859_1)
		if (zafCodeSet->ConvertToOSString(resourceName, buff, false))
#	else
		strcpy(buff, resourceName);
		if (buff[0])
#	endif
		{
			c2pstr(buff);
			handle = GetNamedResource('ICON', (StringPtr)buff);
		}
	}
#elif defined(ZAF_INDEPENDENT)
	handle = mask = 0;
#endif
}

ZafIconData::ZafIconData(const ZafIconStruct &copy) :
	ZafImageData()
{
	// Initialize the information.
	array = ZAF_NULLP(ZafLogicalColor);
	SetImage(*this, copy);
#if !defined(ZAF_TEXT_MODE)
	ZafDisplay::InitializeOSIcon(*this);
#endif
}

ZafIconData::ZafIconData(const ZafIconData &copy) :
	ZafImageData(copy)
{
	// Initialize the image information.
	array = ZAF_NULLP(ZafLogicalColor);
	SetIcon(copy);
}

ZafIconData::~ZafIconData(void)
{
	// Destroy the color handle and mask.
	if (zafDisplay)
	{
		if (!StaticHandle())
			zafDisplay->DestroyOSIcon(*this);
		if (!StaticArray())
			zafDisplay->DestroyZafIcon(*this);
	}
	else if (array && !StaticArray())
	{
		delete []array;
		array = ZAF_NULLP(ZafLogicalColor);
	}
}

void ZafIconData::Clear(void)
{
	// Destroy the color handle and mask.
	PushLevel();
	if (zafDisplay)
	{
		zafDisplay->DestroyOSIcon(*this);
		zafDisplay->DestroyZafIcon(*this);
	}
	SetError(ZAF_ERROR_NONE);
	PopLevel();
}

ZafData *ZafIconData::Duplicate(void)
{
	return (new ZafIconData(*this));
}

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

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

#if defined(ZAF_TEXT_MODE)
ZafError ZafIconData::SetIcon(int, int,	ZafLogicalColor *)
{
	// Return success.
	return (ZAF_ERROR_NONE);
}

ZafError ZafIconData::SetIcon(const ZafIconStruct &)
{
	// Return success.
	return (ZAF_ERROR_NONE);
}
#else
ZafError ZafIconData::SetIcon(int tWidth, int tHeight,
	ZafLogicalColor *tArray)
{
	// Clear the current os handles.
	if (zafDisplay)
		zafDisplay->DestroyOSIcon(*this);

	// Reset the icon information.
	PushLevel();
	SetImage(*this, tWidth, tHeight, tArray);
	PopLevel();

	// Return success.
	return (ZAF_ERROR_NONE);
}

ZafError ZafIconData::SetIcon(const ZafIconStruct &copy)
{
	// Clear the current os handles.
	if (zafDisplay)
		zafDisplay->DestroyOSIcon(*this);

	// Reset the icon information.
	PushLevel();
	SetImage(*this, copy);

	// Update the os handles.
	staticHandle = copy.staticHandle;
	if (staticHandle)
		ZafDisplay::ResetOSIcon(*this, copy);
	PopLevel();

	// Return success.
	return (ZAF_ERROR_NONE);
}
#endif

// ----- Persistent functions -----------------------------------------------
#if defined(USE_ZAF_PERSISTENCE)
ZafIconData::ZafIconData(const ZafIChar *name, ZafDataPersistence &persist) :
	ZafImageData(name, persist.PushLevel(className, classID, ZAF_PERSIST_ROOT_DIRECTORY))
{
	// Set the default icon information.
	InitializeImage(*this);

	staticHandle = false;
#if !defined(ZAF_TEXT_MODE)
	ZafDisplay::InitializeOSIcon(*this);
#endif
	// Read the data.
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafIconData::ReadData(persist);

	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

ZafElement *ZafIconData::Read(const ZafIChar *name, ZafDataPersistence &persist)
{
	return (new ZafIconData(name, persist));
}

void ZafIconData::ReadData(ZafDataPersistence &persist)
{
	// Read the data.
	ZafFile *file = persist.CurrentFile();
	*file >> width >> height;
	array = new ZafLogicalColor[width * height];
	file->Read(array, sizeof(ZafLogicalColor), width * height);
}

void ZafIconData::Write(ZafDataPersistence &persist)
{
	// Read the image information.
	ZafImageData::Write(persist.PushLevel(className, classID, ZAF_PERSIST_ROOT_DIRECTORY));
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafIconData::WriteData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

void ZafIconData::WriteData(ZafDataPersistence &persist)
{
	// Write the image information.
	ZafFile *file = persist.CurrentFile();
	*file << width << height;
	if (array)
		file->Write(array, sizeof(ZafLogicalColor), width * height);
}
#endif
