#include	<stdio.h>
#include	<exec/types.h>
#include	<exec/tasks.h>
#include	<exec/ports.h>
#include	<graphics/displayinfo.h>
#include	<exec/tasks.h>
#include	<dos/dosextens.h>
#include	<intuition/intuition.h>
#include	<clib/exec_protos.h>
#include	<clib/intuition_protos.h>
#include	"/includes/convert.h"
#include	"/includes/struct.h"
#include	"/includes/tom_gadget.h"

struct my_data	*p_info;
struct my_data	dummy_info;
struct	appel_proc	*p_data_proc;
struct	appel_proc	dummy;

struct	Library	*IntuitionBase;
struct	Library	*GfxBase;
extern	struct	tom_gadget	my_gadg[];
extern	void	__saveds	dark();
extern	void	proc_init();
extern	void	proc_end();
extern	char	*p_text_info;

BPTR	hd=0;
char	pr_buff[100];

struct MsgPort      *portptr,*rport;
struct IntuiMessage *imsg, quitmsg;

char *portname = "MyScreenBlanker";

// Signals sent from MachIV to your port.

#define BLANK   1
#define UNBLANK 2
#define QUIT    3

UWORD	flg_blank,flg_quit;

void	__saveds	wait_end();
void	setup();
void	get_msg();

/* Note: The folloing SPrintF Routine is taken from the program "FracBlank " */
/* by:									     */
UWORD PutChar[2] = {0x16C0,0x4E75};

/* dirty hack to avoid assembler part :-)
   16C0: move.b d0,(a3)+
   4E75: rts
*/

#define VOID_STDARGS   void __stdargs

VOID_STDARGS SPrintF(char *pr_buff,char *FormatString,...)

{
 RawDoFmt (FormatString,(APTR)((LONG *)&FormatString+1L),
           (void *)PutChar,pr_buff);
}
mystrlen(char	*pc)
{
	int	ret;
	ret=0;
	while(*pc++!=0){
		ret++;
	}
	return	ret;
}

void	MyWrite(char	*pc)
{
	if(hd!=0)Write(hd,pc,mystrlen(pc));
}

#ifdef	DEBUG
VOID_STDARGS printt(char *FormatString,...)

{
	char	buffer[100];
	 RawDoFmt (FormatString,(APTR)((LONG *)&FormatString+1L),
           (void *)PutChar,buffer);
	MyWrite(buffer);
}
#endif

/* Checrche une resolution correspondant aux mieu a nos demandes */
/* Si *p_depth>=0, on cherche une profondeur max		 */
/* Si *p_tx>=0 , on cherche une taille max			 */

int	find_res(USHORT flg_depth,SHORT *p_depth,SHORT *p_tx,SHORT *p_ty,ULONG *p_d_id)
{
 struct ModeNode *ModeNode;
 struct ModeNode *ModeNodeFound;

 ModeNode=(struct ModeNode *)p_data_proc->ml->lh_Head;
 ModeNodeFound=ModeNode;

 while (ModeNode->mn_Node.ln_Succ)
  {
	if(flg_depth){
		if(*p_depth<ModeNode->MaxDepth){
			*p_depth=ModeNode->MaxDepth;
			if(*p_tx<=ModeNode->MaxX){
				*p_tx=ModeNode->MaxX;
				if(*p_ty<=ModeNode->MaxY){
					*p_ty=ModeNode->MaxY;
				}
			}
			ModeNodeFound=ModeNode;
		}
	}else{
		if(*p_tx<=ModeNode->MaxX){
			*p_tx=ModeNode->MaxX;
			if(*p_ty<=ModeNode->MaxY){
				*p_ty=ModeNode->MaxY;
				if(*p_depth<ModeNode->MaxDepth){
					*p_depth=ModeNode->MaxDepth;
				}
			}
			ModeNodeFound=ModeNode;
		}
	}
	ModeNode=(struct ModeNode *)ModeNode->mn_Node.ln_Succ;
  }
  *p_depth=ModeNodeFound->MaxDepth;

  *p_tx=ModeNodeFound->MaxX;
  *p_ty=ModeNodeFound->MaxY;

  *p_d_id=ModeNodeFound->DisplayID;

  return TRUE;
}

_main(line)
register	char	*line;
{
    struct	Task	*my_t;

   /****************************************************************/
   /* Recherche du port qui contient les infos relatives a l'ecran */
   /* Ce port permet de passer des donnes de la tache main vers ici*/ 
   /****************************************************************/

   IntuitionBase=(struct Library *)OpenLibrary("intuition.library",0);
   GfxBase=(struct Library *)OpenLibrary("graphics.library",0);
#ifdef	DEBUG
   hd=(char *)Open("con:10/10/320/80/",MODE_OLDFILE);
#endif
   setup();

	/*********************************************/
	/* On recupere les informaitons ainsi passee */
	/*********************************************/
	p_data_proc=&dummy;
	p_info=&dummy_info;
	p_data_proc->p_gadg=my_gadg;
	p_data_proc->p_texte=p_text_info;
	p_data_proc->type_screen=SCR_OWN;
	proc_init();

	/* Si on n'a pas encore notifie le type de version */
	if(p_data_proc->code_ret==-1){
		p_data_proc->code_ret=DARK_WB_13;
	}

	my_t=FindTask(0);
#ifdef	DEBUG
	MyWrite("Avant le do\n");
	SPrintF(pr_buff,"Tache mt:%lx\n",my_t);
	MyWrite(pr_buff);
#endif
	flg_blank=FALSE;
	flg_quit=FALSE;
     	wait_end();
	proc_end();

#ifdef	DEBUG
     Close(hd);
#endif
  RemPort(portptr);  // portptr must be valid or we wouldn't be here.

  DeleteMsgPort(portptr);

  if (IntuitionBase)
    CloseLibrary((struct Library*)IntuitionBase);
  if (GfxBase)
    CloseLibrary((struct Library*)GfxBase);

    return 0;
}

void	setup()
{
  // First see if we are already running. If so, Put a message telling it
  // to quit. Wait for SimpleBlanker to Reply.

  if ((portptr = FindPort((STRPTR)portname)) != NULL) {
    if (rport = CreateMsgPort()) {   // Create a reply port for us.
      quitmsg.ExecMessage.mn_Node.ln_Type = NT_MESSAGE;
      quitmsg.ExecMessage.mn_ReplyPort = rport;
      quitmsg.ExecMessage.mn_Length = 32;
      quitmsg.Class = QUIT;
      PutMsg(portptr,(struct Message*)&quitmsg);
      WaitPort(rport); // Wait for SimpleBlanker does a ReplyMsg();
      GetMsg(rport);
      DeleteMsgPort(rport);
      exit(0);
    }
  }
  // Port not found so create and add our port.

  if ((portptr = CreateMsgPort()) == NULL)
    exit(0);

  portptr->mp_Node.ln_Pri = 1;         // Will be searched for.
  portptr->mp_Node.ln_Name = portname;

  AddPort(portptr);

}

int	__saveds	tst_end()
{

	get_msg();

	return (!flg_blank);
}

void	get_msg()
{
    int action;

    while (imsg = (struct IntuiMessage *)GetMsg(portptr)) {
      action = imsg->Class;
      ReplyMsg((struct Message *)imsg);

      switch (action) {
        case BLANK:
	    if(flg_blank==FALSE){
		    flg_blank=TRUE;
	  	    dark();
	     }

            break;                   // UNBLANK falls through!!
        case UNBLANK:
	  flg_blank=FALSE;
          break;
        case QUIT:
	  flg_quit=TRUE;
          break;
      }
    }
}
void	__saveds	wait_end()
{
  while(flg_quit==FALSE) {
    WaitPort(portptr); // Waiting for BLANK or QUIT
    get_msg();
  }
}

