/************************************************************************/
/*									*/
/*	File input.c							*/
/*									*/
/************************************************************************/
/* 									*/
/*									*/
/*									*/
/************************************************************************/

#include <exec/types.h>
#include <dos/dos.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/view.h>
#include <libraries/commodities.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include "/includes/struct.h"
#include "/includes/tom_gadget.h"

#include <clib/commodities_protos.h>
#include <dos/rdargs.h>
#include "gid_main.h"

/* I don't want to include alib_protos.h, because this will make warning */
/* with all printf()							*/
CxObj *HotKey(UBYTE *,struct MsgPort *,long);

#define reg register
#define	NOK	1
#define	OK	0

#define	EVT_HOTKEY	1
#define	EVT_BLANKKEY	2

#define	ABS(x)	(x<0?x:-x)

struct NewBroker newbroker = {
	NB_VERSION,
	"SuperDark",
	"SuperDark V1.5 @93 Thomas Landspurg",
	"Multi-modules Screen Blanker",
	NBU_NOTIFY|NBU_UNIQUE,COF_SHOW_HIDE,0,NULL,0};
extern	struct	tom_gadget	my_gadg[];

struct my_data	my_info;
struct	MsgPort	*broker_mp=NULL;
CxObj	*broker,*cocustom;
CxObj	*coshow=NULL;
CxObj	*coblank=NULL;
ULONG	signal=0;
ULONG	cosigflag,cxobjsignal;
extern	ULONG	cxsigflag;

UBYTE	inputopen = -1;
struct	IOStdReq *inputreq = NULL;
struct Interrupt myhandler;		/* input handler */
long	lsec=0;

extern	struct	Library	*IntuitionBase;
extern	struct	Library	*CxBase;

static	int	waiting=0;
extern	UBYTE	flg_debug;

/**********************************************************/
/* This is the input event handler.			 */
/**********************************************************/

void	__saveds CxFunction(register struct CxMsg *cxm,CxObj *co)
{
	struct InputEvent *ev;
	UWORD	dispatch;
	dispatch=TRUE;
	ev=(struct InputEvent *)CxMsgData(cxm);
	while (ev) {

		/* Si il y a mvt de la souris ou frappe de touche, on remet la	*/
		/* tempo a 0. Si de plus, on avait envoyer un signal de blank	*/
		/* et bien on renvoi un signal de chgt				*/

	      if ((ev->ie_Class == IECLASS_RAWKEY) || (ev->ie_Class == IECLASS_RAWMOUSE)){
			if(my_info.flg_stop==1){
				if(my_info.flg_send==1){
				   Signal(my_info.task,1<<my_info.sigstop);
					dispatch=FALSE;
				}
			}
			waiting = 0;
		}

		/* Evenement timer, sert a compter la non activitee du clavier */

		if ((ev->ie_Class == IECLASS_TIMER)){

			register struct IntuitionBase *ib =(struct IntuitionBase *) IntuitionBase;
			register short  mousey;
			register struct	Screen *scr = ib->FirstScreen;

		      if ((ev->ie_TimeStamp.tv_secs != lsec)) {
			lsec = ev->ie_TimeStamp.tv_secs;

			/* Si on est en mode aleatoire */
			if(my_info.flg_alea==TRUE){
				if((my_info.flg_stop==1)&&(waiting<my_info.tempo)){
					waiting=my_info.tempo;
				}
		        	if(waiting<my_info.tempo_end+1+my_info.tempo)
					waiting = waiting + 1;
			}else{
		        	if(waiting<my_info.tempo+1)
					waiting = waiting + 1;
			}
			my_info.debug1=waiting;
	              }

		     /* Si coin inferieur gauche, blanking immediat, mais */
		     /* seuleument si la souri n'a pas bouge depuis plus  */
		     /* de 3 secondes					  */
		     my_info.debug2=ib->MouseY;
		     if (waiting==2){

			mousey = ib->MouseY;
			if (!(scr->ViewPort.Modes & LACE)){
				mousey >>=1;
			}
			my_info.debug2=scr->Height-mousey;
			if(	(scr->Height-mousey<6)){
				if(ib->MouseX<4){
					if(my_info.flg_stop==0){
						Signal(my_info.task,1<<my_info.sigstart);
						waiting=my_info.tempo+1;
					}
				}
				/* Si coin inferieur droit...pas de blank */
				if(scr->Width -ib->MouseX<4){
					waiting=0;
				}
			  }
		     }

		}
		ev = ev->ie_NextEvent;
	}
	if(my_info.flg_send==1){

		/********************************************************/
		/* Si il n'y a pas eu d'activitee depuis belle lurette	*/
		/* on declenche une tempo de non activitee		*/
		/********************************************************/
		
		if((waiting==my_info.tempo)&&(my_info.flg_stop==0)){
			Signal(my_info.task,1<<my_info.sigstart);
			waiting++;
		}
	
		/********************************************************/
		/* Si on arrive a la fin de la deuxieme temporisation,	*/
		/* on indique qu'il faut  arreter l'effet en cours	*/
		/* mais on remet la tempo juste avant la valeur maximum	*/
		/* de non activitee, pour que tout de suite un autre 	*/
		/* effet soit lance (Mode "aleatoire")			*/
		/********************************************************/
		if((waiting==my_info.tempo_end+my_info.tempo)&&(my_info.flg_alea==TRUE)){
		        Signal(my_info.task,1<<my_info.signext);
			waiting = my_info.tempo+1;
		}
	}
	if(dispatch){
		DivertCxMsg(cxm,co,co);
	}
}

/************************************************************ RemoveHotKey() */
RemoveHotKey(CxObj *co)
{
	if (co){
		RemoveCxObj (co);
		DeleteCxObj (co);
	}
}

/************************************************************ SetHotKey() */

CxObj	*SetHotKey(UBYTE *name,CxObj *co,LONG ev)
{
	RemoveHotKey(co);
	if((co=HotKey(name,broker_mp,ev))==0){
		printd("Hotkey failed\n");
		return(NULL);
	}
	printd("Hotkey:%s\n",name);
	AttachCxObj(broker,co);
	return co;
}
/************************************************************ reset_key() */
/* This function reset the hot key */
/* input:the pos.   of the element */
/* in the my_gadg array		   */

void	ResetKey(int	id)
{
	CxObj	*co;
	LONG	ev;

	if(id==GID_CXPOPKEY){
		co=coshow;
		ev=EVT_HOTKEY;
	}
	if(id==GID_BLANKKEY){
		co=coblank;
		ev=EVT_BLANKKEY;
	}
	SetHotKey((UBYTE *)my_gadg[id].p_data,co,ev);
}

/********************************************************/
/* This is the initialisation of my input event handler */
/********************************************************/

int	init_input_ev(int	argc,char **argv)
{
	UBYTE	**ttypes;

	my_info.task=(struct Task *)FindTask(0);
	broker_mp=(struct MsgPort *)CreateMsgPort ();
	if(broker_mp==0){
		printf("Create Msg port failed\n");
		return(TRUE);
	}
	cxsigflag=1L<<broker_mp->mp_SigBit;
	newbroker.nb_Port=broker_mp;
	ttypes=ArgArrayInit(argc,argv);

	/* Find a tool type with CX_PRIORITY */
/*	newbroker.nb_Pri=0;*/
	newbroker.nb_Pri=(BYTE)ArgInt(ttypes,"CX_PRIORITY",0);

	/* If this CxBroker fail, there is bug chance that's because */
	/* another SuperDark is running. So, the other one will open */
	/* his window!						     */
	if((broker=CxBroker(&newbroker,NULL))==0){
		return(TRUE);
	}
	/* Creation of the hotkey Cxobjects...*/
	ResetKey(GID_CXPOPKEY);
	ResetKey(GID_BLANKKEY);

	if(cocustom=CxCustom(CxFunction,0)){
		AttachCxObj(broker,cocustom);
		ActivateCxObj(broker,1L);
	}else{
		return(TRUE);
	}

	my_info.flg_stop=0;
	my_info.flg_send=1;

	my_info.sigstart=AllocSignal(-1);
	my_info.sigstop=AllocSignal(-1);
	my_info.signext=AllocSignal(-1);
	if((my_info.sigstart==-1)
	 ||(my_info.sigstop==-1)
	 ||(my_info.signext==-1)){
		printf("allocsignal failed\n");
		return(TRUE);
	}
	return(FALSE);
}

/******************************************************************/
/* This is the liberation of the previously allocated ressources  */
/* of the input event						  */
/******************************************************************/

void	free_input_ev()
{
	CxMsg	*msg;
	DeleteCxObjAll(broker);
        if (broker_mp){
		while(msg=(CxMsg *)GetMsg(broker_mp)){
			ReplyMsg((struct Message *)msg);
		}
		DeletePort (broker_mp);
	}
	ArgArrayDone();
	if(my_info.signext!=-1)FreeSignal(my_info.signext);
	if(my_info.sigstart!=-1)FreeSignal(my_info.sigstart);
	if(my_info.sigstop!=-1)FreeSignal(my_info.sigstop);
} 

int	ProcessMsg(ULONG	sig)
{
	CxMsg	*msg;
	ULONG	msgid,msgtype;
	int	code_ret;

	code_ret=1;
	while(msg=(CxMsg *)GetMsg(broker_mp)){

		msgid  =CxMsgID(msg);
		msgtype=CxMsgType(msg);

		ReplyMsg((struct Message *)msg);
		printd(" msgtype:%ld msgid:%ld\n",msgtype,msgid);
		switch(msgtype){
		   case CXM_IEVENT:
		      switch(msgid){

			case EVT_HOTKEY:
				printd("show()\n");
				show();
				break;
			case EVT_BLANKKEY:
				printd("blank()\n");
				Signal(my_info.task,1<<my_info.sigstart);
				waiting=my_info.tempo+1;
				break;
			default:
				printd("Unknow id\n");
				break;
		      }
		   case CXM_COMMAND:
		     switch(msgid){
			case CXCMD_APPEAR:
			case CXCMD_UNIQUE:
				show();
				break;
			case CXCMD_DISAPPEAR:
				press_hide();
				break;
			case CXCMD_DISABLE:
				ActivateCxObj(broker,0L);
				break;
			case CXCMD_ENABLE:
				ActivateCxObj(broker,1L);
				break;
			case CXCMD_KILL:
				stop();
				code_ret=0;
				break;
			break;
		     }
		}
	}
	return code_ret;
}
