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

#include <z_evtmgr.hpp>
#include <z_scrdsp.hpp>
#include <z_sysevt.hpp>
#include <z_logevt.hpp>
#include <z_win.hpp>

// ----- ZafEventManager ----------------------------------------------------

#define GET_NEXT_EVENT (XtIMXEvent | XtIMAlternateInput)

int ZafEventManager::Get(ZafEventStruct &event, ZafQFlags flags)
{
	// Initialize the variables.
	ZafDevice *device;
	ZafQueueElement *element;
	int error = -1;

	// Stay in loop while no event conditions are met.
	do
	{
		// Call all the polled devices.
		if (PollDevices(flags))
		{
			// Check for a user-device to do special message polling.
			if ((Blocked(flags) && !queueBlock.First()) ||
				(!queueBlock.Full() && 
				(XtAppPending(((ZafScreenDisplay	*)ZafDevice::display)->xAppContext)	& GET_NEXT_EVENT)))
			{
				// Block if necessary and process one X event.
				XEvent message;
				blocking = true;
				XtAppNextEvent(((ZafScreenDisplay *)ZafDevice::display)->xAppContext, &message);
				blocking = false;
				ZafEventStruct event(E_MOTIF, &message);
				Put(event, Q_BEGIN);
			}

			// Check for any polled events.
			for (device = First(); device; device = device->Next())
				device->Poll();
		}

		// Get the event.
		element = ReadFromEnd(flags) ? queueBlock.Last() : queueBlock.First();
		if (element)
		{
			event = element->event;
			if (DestroyEvent(flags))
				queueBlock.Subtract((ZafElement *)element);
			error = 0;		// Normal operation of the event manager.
		}
		else if (!Blocked(flags))
		{
			// Set event.type to a NO OP so don't continue processing last
			// event.
			event.type = L_NONE;
			return (-2);	// No events were in queue.
		}
	} while (error);

	// 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;
	}

	if (blocking && !XtAppPending(((ZafScreenDisplay *)ZafDevice::display)->xAppContext))
	{
		XEvent pollEvent;
		pollEvent.type = ClientMessage;
		pollEvent.xclient.message_type = 0;
		pollEvent.xclient.format = 32;
		if (zafWindowManager->First())
			 XSendEvent(((ZafScreenDisplay *)ZafDevice::display)->xDisplay, 
				XtWindow(zafWindowManager->First()->screenID), true, 
				NoEventMask, &pollEvent);
		blocking = false;
	}	

	return (returnValue);
}

void ZafEventManager::UnBlock(void)
{
}

