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

#include <z_evtmgr.hpp>
#include <w_app.hpp>
#include <z_logevt.hpp>

// ----- ZAF_EVENT_STRUCT_MANAGER ---------------------------------------------------

int ZafEventManager::Get(ZafEventStruct &event, ZafQFlags flags)
{
	int error = 0;
	bool finished = false;
	while (!finished && !error)
	{
		// Allow devices (and Windows) to place events in the Zinc queue.
		// Don't get new events until all old ones have been processed.
		// This will prevent pulling the same message (WM_PAINT, for example)
		// off the Windows queue if we haven't been able to process it yet,
		// since Windows leaves some events on the queue until they've
		// actually been processed.
		if (PollDevices(flags))
		{
			// Get a Windows message.
			// Block (wait for a windows message) only if queue is empty
			// and the Q_NO_BLOCK flag is not set.
			MSG msg;
			bool winQueueEmpty = PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE) ? false : true;
			bool zafQueueEmpty = queueBlock.First() ? false : true;
			if (!queueBlock.Full() && (!winQueueEmpty || 
				(zafQueueEmpty && Blocked(flags))) &&
				(DestroyEvent(flags) || zafQueueEmpty))
			{
				// Get a Windows message and place it in the Zinc event queue.
				GetMessage(&msg, 0, 0, 0);
				Put(ZafEventStruct(E_MSWINDOWS, &msg), ReadFromEnd(flags) ? Q_END : Q_BEGIN);
			}

			// Poll all devices for events.
			for (ZafDevice *device = First(); device; device = device->Next())
				device->Poll();
		}

		// Get the event off of the Zinc queue.
		ZafQueueElement *element = ReadFromEnd(flags) ? queueBlock.Last() :
			queueBlock.First();
		if (element)
		{
			// Copy the event.
			event = element->event;

			// Remove the event from the queue.
			if (DestroyEvent(flags))
				queueBlock.Subtract((ZafElement *)element);

			finished = true;	// Processing is finished.
		}
		else if (!Blocked(flags))
		{
			// Set event.type to a NO OP so don't continue processing last
			// event.
			event.type = L_NONE;
			error = -2;			// No events were in the queue.
		}
	};

	// Return the error status.
	return (error);
}

bool ZafEventManager::Put(const ZafEventStruct &event, ZafQFlags flags)
{
	// Place the event back in the event queue.
	bool returnValue = false;
	ZafQueueElement *element;
	if (ReadFromEnd(flags))
		element = (ZafQueueElement *)queueBlock.Add(ZAF_NULLP(ZafQueueElement));
	else
		element = (ZafQueueElement *)queueBlock.Add(queueBlock.First());
	if (element)
	{
		element->event = event;
		returnValue = true;
	}

	return (returnValue);
}

void ZafEventManager::UnBlock(void)
{
}

