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

#include <z_timer.hpp>

// ----- ZafTimer -----------------------------------------------------------

ZafEventType ZafTimer::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	case D_ON:
		deviceState = D_ON;
		if (intervalID)
			break;
		// Continue.

	case D_INITIALIZE:
		intervalID = XtAppAddTimeOut(((ZafScreenDisplay *)display)->xAppContext, interval,
			(XtTimerCallbackProc)TimeOut, (XtPointer)this);
		break;

	case D_OFF:
		deviceState = D_OFF;
		// Continue.

	case D_DEINITIALIZE:
		if (intervalID)
			XtRemoveTimeOut(intervalID);
		intervalID = 0;
		break;

	case D_STATE:
		ccode = DeviceState();
		break;

	case S_ADD_OBJECT:
		Add(event.windowObject);
		break;

	case S_SUBTRACT_OBJECT:
		Subtract(event.windowObject);
		break;

	default:
		ccode = S_UNKNOWN;
		break;
	}

	// Return the control code.
	return (ccode);
}

void ZafTimer::Poll(void)
{
}

unsigned long ZafTimer::SetInterval(unsigned long tInterval)
{
	interval = tInterval;
	return (interval);
}

void ZafTimer::TimeOut(ZafTimer *timer, XtIntervalId *)
{
	// Check for an active timer.
	if (timer->DeviceState() == D_OFF)
		return;

	// Call the specified notification objects.
	ZafEventStruct event;
	event.device = timer;
	for (ZafNotifyList::ZafNotifyElement *element = timer->notifyList.First(); element; element = element->Next())
	{
		event.type = element->notifyMessage ? element->notifyMessage : timer->notifyMessage;
		event.route = ZAF_NULLP(ZafWindowObject);
		if (timer->QueueEvents())
		{
			event.route = element->notifyObject;
			eventManager->Put(event);
		}
		else
			element->notifyObject->Event(event);
	}

	// Check for queued events.
	if (timer->QueueEvents())
	{
		// Generate an XEvent to guarantee devices will be polled.
		XEvent pollEvent;
		pollEvent.type = ClientMessage;
		pollEvent.xclient.message_type = 0;
		pollEvent.xclient.format = 32;
		if (zafWindowManager->First())
			 XSendEvent(((ZafScreenDisplay *)display)->xDisplay, 
				XtWindow(zafWindowManager->First()->screenID), true, 
				NoEventMask, &pollEvent);

		// If there is no notifyList element then just place the event on the
		// queue.
		if (!timer->notifyList.First())
		{
			event.type = timer->notifyMessage;
			event.route = ZAF_NULLP(ZafWindowObject);
			eventManager->Put(event);
		}
	}

	// Re-seed the timer.
	timer->Event(D_INITIALIZE);
}

