/************************************************************************/
/*									*/
/*	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/dos.h>
#include <libraries/dosextens.h>
#include "/includes/struct.h"

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

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

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

extern	struct	Library	*IntuitionBase;

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

struct InputEvent * __saveds __asm myproc_Handler
			(reg __a0 struct InputEvent *ev,reg __a1 struct my_data *info)
{
	struct InputEvent *inev;
	static	int	waiting=0;

	inev = ev;
	while (ev) {

		/* Ici, c'est le test pour l'envoi d'un signal de reactivation	*/
		/* de la fenetre, si on recoit shift gauche+f3			*/

	      if ((ev->ie_Class == IECLASS_RAWKEY)&&
		(ev->ie_Code==0x52)&&
		((ev->ie_Qualifier&IEQUALIFIER_LSHIFT)==IEQUALIFIER_LSHIFT)){
			Signal(info->task,1<<info->sigshow);
			inev=ev->ie_NextEvent;
		}



		/* Si on recoit une demande d'immediate blanking	*/

	      if ((ev->ie_Class == IECLASS_RAWKEY)&&
		(ev->ie_Code==0x53)&&
		((ev->ie_Qualifier&IEQUALIFIER_LSHIFT)==IEQUALIFIER_LSHIFT)){
			if(info->flg_stop==0){
				Signal(info->task,1<<info->sigstart);
				inev=ev->ie_NextEvent;
				waiting=my_info.tempo+1;
			}
		}
		/* 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(info->flg_stop==1){
				if(my_info.flg_send==1){
				   Signal(info->task,1<<info->sigstop);
				}
			}
			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(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<4)){
				if(ib->MouseX<2){
					if(info->flg_stop==0){
						Signal(info->task,1<<info->sigstart);
						waiting=my_info.tempo+1;
					}
				}
				/* Si coin inferieur droit...pas de blank */
				if(scr->Width -ib->MouseX<2){
					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)&&(info->flg_stop==0)){
			Signal(info->task,1<<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)&&(info->flg_alea==TRUE)){
		        Signal(info->task,1<<my_info.signext);
			waiting = my_info.tempo+1;
		}
	}
	return (inev);
}

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

int	init_input_ev()
{
	port=(struct MsgPort *)CreatePort ("p", 0L);
	my_info.flg_stop=0;
	my_info.flg_send=1;
	my_info.sigshow=AllocSignal(-1);
	if(my_info.sigshow==-1){
		printf("allocsignal show failed\n");
		return(TRUE);
	}
	my_info.sigstart=AllocSignal(-1);
	if(my_info.sigstart==-1){
		printf("allocsignal failed\n");
		return(TRUE);
	}
	my_info.sigstop=AllocSignal(-1);
	if(my_info.sigstop==-1){
		printf("allocsignal failed\n");
		return(TRUE);
	}
	my_info.signext=AllocSignal(-1);
	if(my_info.signext==-1){
		printf("allocsignal failed\n");
		return(TRUE);
	}
	my_info.task=(struct Task *)FindTask(0);

	if ( (inputreq = (struct IOStdreq *)CreateStdIO (port)) ==NULL){
		printf("stdio failed\n");
		return(TRUE);
	}
	inputopen = OpenDevice ("input.device", 0L, inputreq, 0L);
	if ( inputopen !=0 ){
		printf("open device failed\n");
		return(TRUE);
	}

	myhandler.is_Code = (void (*)())myproc_Handler;
	myhandler.is_Data =(APTR)&my_info;
	myhandler.is_Node.ln_Pri = 51;
	inputreq->io_Command = IND_ADDHANDLER;
	inputreq->io_Data =(APTR) &myhandler;
	DoIO (inputreq);

	return(FALSE);
}

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

void	free_input_ev()
{
	if(inputreq){
		inputreq->io_Command = IND_REMHANDLER;
		inputreq->io_Data = (APTR)&myhandler;
		DoIO (inputreq);
	}
	if (!inputopen) CloseDevice (inputreq);
	if(inputreq)DeleteStdIO (inputreq);
	if(my_info.signext!=-1)FreeSignal(my_info.signext);
	if(my_info.sigstart!=-1)FreeSignal(my_info.sigstart);
	if(my_info.sigshow!=-1)FreeSignal(my_info.sigshow);
	if(my_info.sigstop!=-1)FreeSignal(my_info.sigstop);
        if (port) DeletePort (port);
} 
