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

#include <exec/memory.h>

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

#include "includes.h"
#include "libraries.h"
#include "protos/protos.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 );
	
	switch( Event->ie_Class )
	{
	case IECLASS_TIMER:
		if( ++timeCount >= Prefs->bp_Timeout )
		{
			InterruptMsg->bm_Flags = BF_INTERNAL;
			InterruptMsg->bm_Type = BM_SENDBLANK;
			PutMsg( ServerPort, ( struct Message * )InterruptMsg );
			timeCount = 0;
		}
		return;
	case IECLASS_RAWMOUSE:
		if(( Event->ie_Code == IECODE_NOBUTTON )&&
		   ( Event->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE )&&
		   ( Prefs->bp_BlankCorner || Prefs->bp_DontCorner ))
		{
			Signal( ServerTask, SIGBREAKF_CTRL_D );
		}
		break;
	case IECLASS_RAWKEY:
		if( Event->ie_Code & IECODE_UP_PREFIX )
			return;
	}

	if( Blanking )
	{
		Blanking = FALSE;
		InterruptMsg->bm_Flags = BF_INTERNAL;
		InterruptMsg->bm_Type = BM_SENDUNBLANK;
		PutMsg( ServerPort, ( struct Message * )InterruptMsg );
	}
	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 );

	return ( cxError == CBERR_OK ) ? OK : QUIT;
}
