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

#include <z_text.hpp>
#define ZAF_TEXT_INFO
#include "gbl_def.cpp"

// ----- ZafText ------------------------------------------------------------

ZafText::ZafText(int left, int top, int width, int height,
	const ZafIChar *text, int maxLength) :
	ZafWindow(left, top, width, height),
	autoClear(false), invalid(false), unanswered(false),
	viewOnly(false), wordWrap(true), hzJustify(ZAF_HZ_LEFT),
	stringData(ZAF_NULLP(ZafStringData))
{
#if defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	editBuffer = ZAF_NULLP(ZafIChar);
#endif
#if !defined(ZAF_TEXT_MODE)
	SetBordered(true);
#endif
	SetDestroyable(false);
	SetMoveable(false);
	SetSizeable(false);

	// Initialize the string data.
	SetStringData(new ZafStringData(text, maxLength));
}

ZafText::ZafText(int left, int top, int width, int height,
	ZafStringData *zStringData) :
	ZafWindow(left, top, width, height),
	autoClear(false), invalid(false), unanswered(false),
	viewOnly(false), wordWrap(true), hzJustify(ZAF_HZ_LEFT),
	stringData(ZAF_NULLP(ZafStringData))
{
#if defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	editBuffer = ZAF_NULLP(ZafIChar);
#endif
#if !defined(ZAF_TEXT_MODE)
	SetBordered(true);
#endif
	SetDestroyable(false);
	SetMoveable(false);
	SetSizeable(false);

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

ZafText::ZafText(const ZafText &copy) :
	ZafWindow(copy),
	autoClear(copy.autoClear), invalid(copy.invalid),
	unanswered(copy.unanswered), viewOnly(copy.viewOnly),
	wordWrap(copy.wordWrap), hzJustify(copy.hzJustify),
	stringData(ZAF_NULLP(ZafStringData))
{
#if defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	editBuffer = ZAF_NULLP(ZafIChar);
#endif

	// Initialize the text information.
	if (copy.StringData()->Destroyable())
		SetStringData(new ZafStringData(*copy.StringData()));
	else
		SetStringData(copy.StringData());
}

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

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

#	if defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	delete []editBuffer;
#	endif
}

ZafEventType ZafText::DragDropEvent(const ZafEventStruct &event)
{
	// Defer to the base class.
	return (ZafWindowObject::DragDropEvent(event));
}

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

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

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

ZafLogicalEvent ZafText::LogicalEvent(const ZafEventStruct &event)
{
	ZafLogicalEvent ccode = MapEvent(defaultEventMap, event);
	return ((ccode == L_NONE) ? ZafWindowObject::LogicalEvent(event) : ccode);
}

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

bool ZafText::SetCopyDraggable(bool setCopyDraggable)
{
	// Defer to the root class.
	return (ZafWindowObject::SetCopyDraggable(setCopyDraggable));
}

bool ZafText::SetDestroyable(bool )
{
	// destroyable is false for this class.
	destroyable = false;
	return (destroyable);
}

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

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

bool ZafText::SetInvalid(bool setInvalid)
{
	// Change the attribute.
	invalid = setInvalid;
	return (invalid);
}

bool ZafText::SetLocked(bool )
{
	// locked is false for this class.
	locked = false;
	return (locked);
}

bool ZafText::SetMaximized(bool )
{
	// maximized is false for this class.
	maximized = false;
	return (maximized);
}

bool ZafText::SetMinimized(bool )
{
	// minimized is false for this class.
	minimized = false;
	return (minimized);
}

bool ZafText::SetModal(bool )
{
	// modal is false for this class.
	modal = false;
	return (modal);
}

bool ZafText::SetMoveable(bool )
{
	// moveable is false for this class.
	moveable = false;
	return (moveable);
}

bool ZafText::SetLinkDraggable(bool setLinkDraggable)
{
	// Defer to the root class.
	return (ZafWindowObject::SetLinkDraggable(setLinkDraggable));
}

bool ZafText::SetMoveDraggable(bool setMoveDraggable)
{
	// Defer to the root class.
	return (ZafWindowObject::SetMoveDraggable(setMoveDraggable));
}

bool ZafText::SetNormalHotKeys(bool )
{
	// normalHotKeys is false for this class.
	normalHotKeys = false;
	return (normalHotKeys);
}

ZafWindow *ZafText::SetOwner(ZafWindow *)
{
	// owner is null for this class.
	owner = ZAF_NULLP(ZafWindow);
	return (owner);
}

bool ZafText::SetParentDrawBorder(bool setParentDrawBorder)
{
	// Defer to the root class.
	return (ZafWindowObject::SetParentDrawBorder(setParentDrawBorder));
}

ZafSelectionType ZafText::SetSelectionType(ZafSelectionType )
{
	// selectionType is ZAF_SINGLE_SELECTION for this class.
	selectionType = ZAF_SINGLE_SELECTION;
	return (selectionType);
}

bool ZafText::SetSizeable(bool )
{
	// sizeable is false for this class.
	sizeable = false;
	return (sizeable);
}

ZafError ZafText::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 ? tStringData : new ZafStringData;

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

bool ZafText::SetTemporary(bool )
{
	// temporary is false for this class.
	temporary = false;
	return (temporary);
}

ZafError ZafText::SetText(const ZafIChar *text)
{
	// Set the os text.
	stringData->SetText(text);
	return (ZAF_ERROR_NONE);
}

bool ZafText::SetUnanswered(bool setUnanswered)
{
	// Make sure the request is valid.
	if (unanswered != setUnanswered)
	{
		// Re-compute the text before resetting the flag.
		if (setUnanswered)
			stringData->Clear();

		unanswered = setUnanswered;
	}

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

bool ZafText::SetViewOnly(bool setViewOnly)
{
	// Check for equivalent flag.
	if (viewOnly != setViewOnly && !screenID)
		viewOnly = setViewOnly;

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

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

const ZafIChar *ZafText::Text(void)
{
	// Get the os text.
	OSGetText();
	return (stringData->Text());
}

ZafError ZafText::Update(ZafText *text, ZafUpdateType type)
{
	ZafError retVal =  ZAF_ERROR_INVALID;
	if (type & ZAF_UPDATE_OBJECT)
		retVal = text->OSSetText();
	if (type & ZAF_UPDATE_DATA)
		retVal =  text->OSGetText();
	
	return (retVal);
}

// ----- Persistent functions -----------------------------------------------
#if defined(USE_ZAF_PERSISTENCE)
ZafText::ZafText(const ZafIChar *name, ZafObjectPersistence &persist) :
	ZafWindow(name, persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY)),
	stringData(ZAF_NULLP(ZafStringData))
{
#if defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	editBuffer = ZAF_NULLP(ZafIChar);
#endif

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

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

void ZafText::ReadData(ZafObjectPersistence &persist)
{
	// Read the text information.
	ZafUInt16 flag1, flag2;
	ZafIChar stringName[ZAF_MAXNAMELEN];
	ZafFile *file = persist.CurrentFile();
	*file >> flag1 >> flag2 >> stringName;
	autoClear = (flag1 & 0x0001) ? true : false;
	invalid = (flag1 & 0x0002) ? true : false;
	unanswered = (flag1 & 0x0004) ? true : false;
	viewOnly = (flag1 & 0x0008) ? true : false;
	wordWrap = (flag1 & 0x0010) ? true : false;
	hzJustify = (ZafHzJustify)((int)flag2 & 0x000F);

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

void ZafText::Write(ZafObjectPersistence &persist)
{
	// Write the object.
	ZafWindow::Write(persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY));
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafText::WriteData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

void ZafText::WriteData(ZafObjectPersistence &persist)
{
	// Make sure information is up-to-date.
	OSGetText();

	// Write the data.
	ZafUInt16 flag1 = 0, flag2 = 0;
	flag1 |= (ZafUInt16)(autoClear ? 0x0001 : 0);
	flag1 |= (ZafUInt16)(invalid ? 0x0002 : 0);
	flag1 |= (ZafUInt16)(unanswered ? 0x0004 : 0);
	flag1 |= (ZafUInt16)(viewOnly ? 0x0008 : 0);
	flag1 |= (ZafUInt16)(wordWrap ? 0x0010 : 0);
	flag2 |= (ZafUInt16)(hzJustify & 0x000F);
	const ZafIChar *stringName = stringData ? stringData->StringID() : ZAF_NULLP(ZafIChar);
	ZafFile *file = persist.CurrentFile();
	*file << flag1 << flag2 << stringName;

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