/*
**	termResponse.c
**
**	Signal event handling routines
**
**	Copyright © 1990-1995 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#include "termGlobal.h"

	/* Yet another function pointer. */

typedef BYTE (* RESPONSE)(VOID);

	/* Signal response table entry. */

struct SignalResponseInfo
{
	RESPONSE	Routine;
	ULONG		Mask;
};

	/* Signal response table. */

STATIC struct SignalResponseInfo	ResponseTable[7];
STATIC WORD				ResponseCount;
STATIC ULONG				ResponseMask;

#ifdef DATAFEED
BPTR DataFeed;
#define CHUNK_LENGTH	20
#define CHAR_DELAY	(1000000/1800)
//#define CHAR_DELAY	0
#endif	/* DATAFEED */

	/* AddResponse(RESPONSE Routine,ULONG Mask):
	 *
	 *	Register a signal response routine.
	 */

STATIC VOID __regargs
AddResponse(RESPONSE Routine,ULONG Mask)
{
	ResponseTable[ResponseCount] . Routine	= Routine;
	ResponseTable[ResponseCount] . Mask	= Mask;

	ResponseMask |= Mask;

	ResponseCount++;
}

	/* HandleResponse():
	 *
	 *	Register routines and corresponding signals,
	 *	wait for events and process them.
	 */

VOID
HandleResponse()
{
	register ULONG	SignalSet;
	register BYTE	Running,
			SerialRunning;
	register WORD	i;

	ResponseMask	= XEM_Signal;
	ResponseCount	= 0;

	AddResponse((RESPONSE)HandleSerialCheck,SIG_CHECK);

	if(WorkbenchPort)
		AddResponse((RESPONSE)HandleWorkbenchWindow,SIG_WORKBENCH);

	if(ReadPort && Status != STATUS_HOLDING && ProcessIO)
	{
		AddResponse(HandleSerial,SIG_SERIAL);

		SerialRunning = TRUE;
	}
	else
		SerialRunning = FALSE;

	if(OwnDevUnitBase && !Config -> SerialConfig -> Shared && OwnDevBit != -1)
		AddResponse(HandleOwnDevUnit,1L << OwnDevBit);

	AddResponse(HandleWindow,SIG_WINDOW);

	if(TermRexxPort)
		AddResponse(HandleRexx,SIG_REXX);

	AddResponse(HandleQueueMsg,SIG_QUEUE);

#ifdef DATAFEED
		/* Wait for events. */

	if(HostReadBuffer || DataHold)
	{
		if(ReadPort && Status != STATUS_HOLDING)
			SignalSet = CheckSignal(ResponseMask) | SIG_SERIAL;
		else
			SignalSet = CheckSignal(ResponseMask);
	}
	else
	{
		if(DataFeed)
			SignalSet = CheckSignal(ResponseMask);
		else
			SignalSet = Wait(ResponseMask);
	}
#else
		/* Wait for events. */

	if(HostReadBuffer || DataHold)
	{
		if(ReadPort && Status != STATUS_HOLDING)
			SignalSet = CheckSignal(ResponseMask) | SIG_SERIAL;
		else
			SignalSet = CheckSignal(ResponseMask);
	}
	else
		SignalSet = Wait(ResponseMask);
#endif	/* DATAFEED */

	if(SignalSet & XEM_Signal)
		HandleExternalEmulation();

	FOREVER
	{
#ifdef DATAFEED
		if(DataFeed)
		{
			UBYTE	LocalBuffer[CHUNK_LENGTH];
			LONG	Len;

			if((Len = Read(DataFeed,LocalBuffer,CHUNK_LENGTH)) > 0)
			{
				STRPTR Index = LocalBuffer;

				if(Marking)
					DropMarker();

				if(CHAR_DELAY)
				{
					do
					{
						ConProcess(Index++,1);

						WaitTime(0,CHAR_DELAY);
					}
					while(--Len);
				}
				else
					ConProcess(LocalBuffer,Len);
			}
			else
			{
				Close(DataFeed);

				DataFeed = NULL;
			}
		}
#endif	/* DATAFEED */

		for(i = 0, Running = FALSE ; !MainTerminated && i < ResponseCount ; i++)
		{
			if(SignalSet & ResponseTable[i] . Mask)
			{
				if((*ResponseTable[i] . Routine)())
					Running = TRUE;
				else
					SignalSet &= ~ResponseTable[i] . Mask;
			}
		}

		if(!SerialRunning && ReadPort && Status != STATUS_HOLDING && ProcessIO)
		{
			AddResponse(HandleSerial,SIG_SERIAL);

			SerialRunning = TRUE;

			SignalSet |= SIG_SERIAL;
		}

		if(Running && !MainTerminated)
			SignalSet |= SetSignal(0,ResponseMask) & ResponseMask;
		else
			break;
	}
}
