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

#include <z_prompt.hpp>
#include <z_string.hpp>
#include <z_ctype.hpp>
#define ZAF_PROMPT_INFO
#include "gbl_def.cpp"

// ----- ZafPrompt ----------------------------------------------------------

ZafPrompt::ZafPrompt(int left, int top, int width, ZafStringData *zStringData) :
	ZafWindowObject(left, top, width, 1),
	stringData(ZAF_NULLP(ZafStringData)), autoSize(true), hotKeyChar(0),
	hotKeyIndex(-1), hzJustify(ZAF_HZ_LEFT), vtJustify(ZAF_VT_TOP), 
	transparentBackground(false)
{
	// Initialize the prompt information.
	SetNoncurrent(true);
	SetBordered(true);
	saveRegion = zafRegion;

	// Initialize the prompt data.
	if (zStringData)
		SetStringData(zStringData);
	else
		SetStringData(new ZafStringData);
}

ZafPrompt::ZafPrompt(int left, int top, int width, const ZafIChar *text) :
	ZafWindowObject(left, top, width, 1),
	stringData(ZAF_NULLP(ZafStringData)), autoSize(true), hotKeyChar(0),
	hotKeyIndex(-1), hzJustify(ZAF_HZ_LEFT), vtJustify(ZAF_VT_TOP),
	transparentBackground(false)
{
	// Initialize the prompt information.
	SetNoncurrent(true);
	SetBordered(true);
	saveRegion = zafRegion;

	// Initialize the prompt data.
	SetStringData(new ZafStringData(text));
}

ZafPrompt::ZafPrompt(const ZafPrompt &copy) :
	ZafWindowObject(copy),
	stringData(ZAF_NULLP(ZafStringData)), autoSize(copy.autoSize),
	hotKeyChar(copy.hotKeyChar), hotKeyIndex(copy.hotKeyIndex),
	hzJustify(copy.hzJustify), vtJustify(copy.vtJustify),
	transparentBackground(copy.transparentBackground),
	saveRegion(copy.saveRegion)
{
	// Initialize the prompt information.
	if (copy.StringData()->Destroyable())
		SetStringData(new ZafStringData(*copy.StringData()));
	else
		SetStringData(copy.StringData());
}

ZafPrompt::~ZafPrompt(void)
{
	// Remove the data notification.
	stringData->SubtractNotification(this, (ZafUpdateFunction)Update);

	// Restore the string information.
	if (stringData->Destroyable() && stringData->NotifyCount() == 0)
		delete stringData;
}

ZafWindowObject *ZafPrompt::Duplicate(void)
{
	return (new ZafPrompt(*this));
}

const ZafPaletteStruct *ZafPrompt::MapClassPalette(ZafPaletteType type, ZafPaletteState state)
{
	const ZafPaletteStruct *palette = MapPalette(defaultPaletteMap, type, state);
	return (palette ? palette : ZafWindowObject::MapClassPalette(type, state));
}

void ZafPrompt::ConvertCoordinates(ZafCoordinateType newCoordinateType)
{
	ConvertRegion(saveRegion, newCoordinateType);
	ZafWindowObject::ConvertCoordinates(newCoordinateType);
}

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

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

ZafRegionStruct ZafPrompt::Region(void) const
{
	return (saveRegion);
}

bool ZafPrompt::SetAcceptDrop(bool )
{
	// acceptDrop is false for this class.
	acceptDrop = false;
	return (acceptDrop);
}

bool ZafPrompt::SetAutoSize(bool setAutoSize)
{
	// Make sure the request is valid.
	if (autoSize != setAutoSize && !screenID)
		autoSize = setAutoSize;

	// Return the current attribute.
	return (autoSize);
}

bool ZafPrompt::SetChanged(bool )
{
	// changed is false for this class.
	changed = false;
	return (changed);
}

bool ZafPrompt::SetCopyDraggable(bool )
{
	// copyDraggable is false for this class.
	copyDraggable = false;
	return (copyDraggable);
}

ZafCoordinateType ZafPrompt::SetCoordinateType(ZafCoordinateType newCoordinateType)
{
	if (coordinateType != newCoordinateType && !screenID)
	{
		if (coordinateType == ZAF_CELL && zafRegion.Height() == 1)
		{
			ZafRegionStruct convertRegion = zafRegion;
			ConvertRegion(convertRegion, newCoordinateType);
			zafRegion.bottom = zafRegion.top + convertRegion.Height() - 1;
			convertRegion = saveRegion;
			ConvertRegion(convertRegion, newCoordinateType);
			saveRegion.bottom = saveRegion.top + convertRegion.Height() - 1;
		}
		coordinateType =
			zafRegion.coordinateType =
			saveRegion.coordinateType =
			newCoordinateType;
	}

	// Return the current attribute.
	return (coordinateType);
}

bool ZafPrompt::SetFocus(bool )
{
	// focus is false for this class.
	focus = false;
	return (focus);
}

ZafLogicalFont ZafPrompt::SetFont(ZafLogicalFont font)
{
	ZafLogicalFont oldFont = ZafWindowObject::SetFont(font);
	if (autoSize && screenID)
	{
		Event(ZafEventStruct(S_COMPUTE_SIZE));
		OSSize();
	}

	return oldFont;
}

const ZafIChar *ZafPrompt::SetHelpContext(const ZafIChar *)
{
	// helpContext is empty for this class.
	return (ZAF_NULLP(ZafIChar));
}

ZafIChar ZafPrompt::SetHotKey(ZafIChar setHotKeyChar, int setHotKeyIndex)
{
	// Make sure the request is valid.
	if (screenID)
		return (hotKeyChar);

	// hotKeyChar affects only the action (keyStroke), and keyKeyIndex
	// affects only the appearance (underline).
	if (hotKeyChar != setHotKeyChar)
		hotKeyChar = ToUpper(setHotKeyChar);
	if (hotKeyIndex != setHotKeyIndex)
		hotKeyIndex = setHotKeyIndex;

	// Return the current hot key.
	return (hotKeyChar);
}

ZafHzJustify ZafPrompt::SetHzJustify(ZafHzJustify setHzJustify)
{
	// Make sure the request is valid.
	if (hzJustify != setHzJustify && !screenID)
		hzJustify = setHzJustify;

	// Return the current attribute.
	return (hzJustify);
}

bool ZafPrompt::SetLinkDraggable(bool )
{
	// linkDraggable is false for this class.
	linkDraggable = false;
	return (linkDraggable);
}

bool ZafPrompt::SetMoveDraggable(bool )
{
	// moveDraggable is false for this class.
	moveDraggable = false;
	return (moveDraggable);
}

bool ZafPrompt::SetNoncurrent(bool )
{
	// noncurrent is true for this class.
	noncurrent = true;
	return (noncurrent);
}

void ZafPrompt::SetRegion(const ZafRegionStruct &region)
{
	zafRegion = saveRegion = region;
	Event(S_COMPUTE_SIZE);
}

ZafRegionType ZafPrompt::SetRegionType(ZafRegionType )
{
	// regionType is ZAF_INSIDE_REGION for this class.
	regionType = ZAF_INSIDE_REGION;
	return (regionType);
}

ZafError ZafPrompt::SetStringData(ZafStringData *tStringData)
{
	// Remove the data notification.
	if (stringData)
		stringData->SubtractNotification(this, (ZafUpdateFunction)Update);

	// Reset the string data.
	if (stringData && stringData != tStringData &&
		stringData->Destroyable() && stringData->NotifyCount() == 0)
		delete stringData;
	stringData = tStringData;

	// Add the data notification.
	if (stringData)
		stringData->AddNotification(this, (ZafUpdateFunction)Update);
	return (OSSetText());
}

ZafError ZafPrompt::SetText(const ZafIChar *text)
{
	// Reset the prompt.
	if (stringData)
		stringData->SetText(text);
	else
		SetStringData(new ZafStringData(text));

	return (ZAF_ERROR_NONE);
}

bool ZafPrompt::SetTransparentBackground(bool setTransparentBackground)
{
	// Make sure the request is valid.
	if (transparentBackground != setTransparentBackground && !screenID)
		transparentBackground = setTransparentBackground;

	// Return the current attribute.
	return (transparentBackground);
}

const ZafIChar *ZafPrompt::Text(void)
{
	// Return the string data's text, if any.
	return (stringData ? stringData->Text() : ZAF_NULLP(ZafIChar));
}

ZafUserFunction ZafPrompt::SetUserFunction(ZafUserFunction )
{
	// userFunction is null for this class.
	userFunction = ZAF_NULLF(ZafUserFunction);
	return (userFunction);
}

ZafVtJustify ZafPrompt::SetVtJustify(ZafVtJustify setVtJustify)
{
	// Make sure the request is valid.
	if (vtJustify != setVtJustify && !screenID)
		vtJustify = setVtJustify;

	// Return the current attribute.
	return (vtJustify);
}

ZafStringData *ZafPrompt::StringData(void) const
{
	return (stringData);
}

ZafError ZafPrompt::Update(ZafPrompt *prompt, ZafUpdateType type)
{
	ZafError retVal = ZAF_ERROR_INVALID;
	if (type & ZAF_UPDATE_OBJECT)
		retVal = prompt->OSSetText();
	if (type & ZAF_UPDATE_HOT_KEY)
	{
		ZafMessageData *message = DynamicPtrCast(prompt->StringData(),
			ZafMessageData);
		if (message)
			prompt->SetHotKey(message->HotKeyChar(), message->HotKeyIndex());
	}

	return (retVal);
}

// ----- Persistent functions -----------------------------------------------
#if defined(USE_ZAF_PERSISTENCE)
ZafPrompt::ZafPrompt(const ZafIChar *name, ZafObjectPersistence &persist) :
	ZafWindowObject(name, persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY)),
	stringData(ZAF_NULLP(ZafStringData))
{
	// Initialize the prompt information.
	saveRegion = zafRegion;

	// Read the data.
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafPrompt::ReadData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

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

void ZafPrompt::ReadData(ZafObjectPersistence &persist)
{
	ZafFile *file = persist.CurrentFile();

	// Read the data.
	ZafUInt16 flag1, flag2, flag3;
	ZafIChar stringName[ZAF_MAXNAMELEN];
	*file >> stringName >> flag1 >> flag2 >> flag3 >> hotKeyIndex;

	autoSize = (flag1 & 0x0001) ? true : false;
	transparentBackground = (flag1 & 0x0002) ? true : false;
	hotKeyChar = (ZafIChar)flag2;
	hzJustify = (ZafHzJustify)((int)flag3 & 0x000F);
	vtJustify = (ZafVtJustify)(((int)flag3 & 0x00F0) >> 4);

	// Read the string data.
	if (stringName[0])
		stringData = new ZafStringData(stringName, persist);

	// Add the data notification.
	if (stringData)
		stringData->AddNotification(this, (ZafUpdateFunction)Update);
}

void ZafPrompt::Write(ZafObjectPersistence &persist)
{
	// Write the object.
	ZafRegionStruct tempRegion = zafRegion;
	zafRegion = saveRegion;
	ZafWindowObject::Write(persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY));
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafPrompt::WriteData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
	zafRegion = tempRegion;
}

void ZafPrompt::WriteData(ZafObjectPersistence &persist)
{
	// Write the data.
	ZafUInt16 flag1 = 0, flag2 = 0, flag3 = 0;
	flag1 |= (ZafUInt16)(autoSize ? 0x0001 : 0);
	flag1 |= (ZafUInt16)(transparentBackground ? 0x0002 : 0);
	flag2 |= (ZafUInt16)hotKeyChar;
	flag3 |= (ZafUInt16)(hzJustify & 0x000F);
	flag3 |= (ZafUInt16)((vtJustify & 0x000F) << 4);

	const ZafIChar *stringName = stringData ? stringData->StringID() : ZAF_NULLP(ZafIChar);
	ZafFile *file = persist.CurrentFile();
	*file << stringName << flag1 << flag2 << flag3 << hotKeyIndex;

	// Write the string data.
	if (stringData)
		stringData->Write(persist);
}
#endif
