/*
 *	Copyright (c) 1993 Michael D. Bayne.
 *	All rights reserved.
 *
 *	Please see the documentation accompanying the distribution for
 *      distribution and disclaimer information.
 */

#include <exec/memory.h>
#include <dos/dos.h>

#include <libraries/commodities.h>
#include <devices/inputevent.h>

#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/commodities_protos.h>
#include <clib/alib_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/commodities_pragmas.h>

#include "defs.h"
#include "Blanker.h"
#include "Garshneblanker_rev.h"

#include "protos/main.h"
#include "protos/winhand.h"
#include "protos/module.h"

BlankMsg *InterruptMsg;
struct MsgPort *CxPort;
CxObj *ServerBroker, *pHotKey, *bHotKey, *objectList;
LONG timeCount = 0;
struct NewBroker nServerBroker = {
	NB_VERSION, "Garshneblanker", VERS, "Screen blanking for the 21st century",
	NBU_UNIQUE|NBU_NOTIFY, COF_SHOW_HIDE, 0, 0, 0
	};

VOID __interrupt __saveds CxBFunc( CxMsg *CxMessage, CxObj *CxObject )
{
	struct InputEvent *Event = ( struct InputEvent * )CxMsgData( CxMessage );
	
	if( Event->ie_Class == IECLASS_TIMER )
	{
		if( ++timeCount >= Prefs->bp_Timeout )
		{
			InterruptMsg->bm_Flags = BF_INTERNAL;
			InterruptMsg->bm_Type = BM_SENDBLANK;
			PutMsg( ServerPort, ( struct Message * )InterruptMsg );
			timeCount = 0;
		}
	}
	else
	{
		if(( Event->ie_Class != IECLASS_RAWKEY )||(!( Event->ie_Code & IECODE_UP_PREFIX )))
		{
			if( Blanking )
			{
				InterruptMsg->bm_Flags = BF_INTERNAL;
				InterruptMsg->bm_Type = BM_SENDUNBLANK;
				PutMsg( ServerPort, ( struct Message * )InterruptMsg );
				Blanking = FALSE;
			}
			timeCount = 0;
		}
	}
}

LONG HandleCxMess( VOID )
{
	LONG msgid, msgtype;
	CxMsg *msg;
	
	while( msg = ( CxMsg * )GetMsg( CxPort ))
	{
		msgid = CxMsgID( msg );
		msgtype = CxMsgType( msg );
		ReplyMsg(( struct Message * )msg );
		
		switch( msgtype )
		{
		case CXM_IEVENT:
			switch( msgid )
			{
			case EVT_CX_POPUP:
				openMainWindow();
				break;
			case EVT_CX_BLANK:
				InterruptMsg->bm_Flags = BF_INTERNAL;
				InterruptMsg->bm_Type = BM_SENDBLANK;
				PutMsg( ServerPort, ( struct Message * )InterruptMsg );
				break;
			}
			break;
		case CXM_COMMAND:
			switch( msgid )
			{
			case CXCMD_DISABLE:
				ActivateCxObj( ServerBroker, 0l );
				break;
			case CXCMD_ENABLE:
				ActivateCxObj( ServerBroker, 1l );
				break;
			case CXCMD_KILL:
				return QUIT;
			case CXCMD_APPEAR:
			case CXCMD_UNIQUE:
				openMainWindow();
				break;
			case CXCMD_DISAPPEAR:
				CloseBlankerWindow();
				CloseDownScreen();
				break;
			default:
				break;
			}
		default:
			break;
		}
	}

	return OK;
}

VOID ShutdownCX( VOID )
{
	CxMsg *msg;
	
	if( InterruptMsg )
		FreeVec( InterruptMsg );

	if( CxPort )
	{
		if( ServerBroker )
			DeleteCxObjAll( ServerBroker );
		ServerBroker = 0L;
		
		while( msg = ( CxMsg * )GetMsg( CxPort ))
			ReplyMsg(( struct Message * )msg );
		DeletePort( CxPort );
		CxPort = 0L;
	}
}

LONG UpdateCX( VOID )
{
	ActivateCxObj( ServerBroker, 0l );
	
	DeleteCxObj( objectList );
	DeleteCxObj( pHotKey );
	DeleteCxObj( bHotKey );
	
	if( objectList = CxCustom( CxBFunc, 0L ))
		AttachCxObj( ServerBroker, objectList );
	if( pHotKey = HotKey( Prefs->bp_PopKey, CxPort, EVT_CX_POPUP ))
		AttachCxObj( ServerBroker, pHotKey );
	if( bHotKey = HotKey( Prefs->bp_BlankKey, CxPort, EVT_CX_BLANK ))
		AttachCxObj( ServerBroker, bHotKey );
	
	if( CxObjError( ServerBroker ))
	{
		ShutdownCX();
		return QUIT;
	}
	else
		ActivateCxObj( ServerBroker, 1l );

	return OK;
}

LONG SetupCX( VOID )
{
	LONG cxError;
	
	if( InterruptMsg = AllocVec( sizeof( BlankMsg ), MEMF_CLEAR|MEMF_PUBLIC ))
	{
		InterruptMsg->bm_Mess.mn_ReplyPort = ServerPort;
		InterruptMsg->bm_Mess.mn_Length = sizeof( BlankMsg );
		
		if( CxPort = CreatePort( 0L, 0L ))
		{
			nServerBroker.nb_Pri = Prefs->bp_Priority;
			nServerBroker.nb_Port = CxPort;
			ServerBroker = CxBroker( &nServerBroker, &cxError );
			if( cxError == CBERR_OK )
				return UpdateCX();
			else
				ShutdownCX();
		}
	}
	
	return QUIT;
}

LONG CheckCX( VOID )
{
	LONG cxError;
	
	ServerBroker = CxBroker( &nServerBroker, &cxError );
	DeleteCxObj( ServerBroker );

	if( cxError == CBERR_OK )
		return OK;

	return QUIT;
}
