/*
lc DigiZP
Blink FROM LIB:cback.o+ ram:DigiZP.o TO DigiZ LIB lib:lc.lib lib:amiga.lib DEFINE __main=__tinymain NODEBUG SMALLCODE SMALLDATA VERBOSE

*/

#include <stdio.h>
#include <exec/types.h>
#include <exec/io.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <workbench/workbench.h>
#include <workbench/icon.h>
#include <workbench/startup.h>
#include <graphics/rastport.h>
#include <graphics/text.h>
#include <devices/timer.h>
#include <libraries/dos.h>
#include <proto/dos.h>
#include <dh1:fichiers/c/digizV2/Interface.c>

#define clk(x) ((x)==1?2:5)
#define spc(x) ((x)==1?30:42)
#define zero(x) ((x)==' '?'0':(x))

/* #define min(x,y) ((x)<(y)?(x):(y)) */
#define conf(max,x) (((x)<(max))&&((x)>=0)?TRUE:FALSE)

char *_procname="DigiZ";
long _priority=20,_BackGroundIO=1,_stack=4000;
extern BPTR _Backstdout;
UBYTE vers[]="\0$VER: DigiZ v2.0 (16.07.93)";

struct RastPort *RPort;
struct Screen *screen;
struct Screen *ascreen;
struct Window *Window;
struct Window *Window2=NULL;
struct IntuitionBase *IntuitionBase;
struct IconBase *IconBase;
struct DiskObject *DiskObj;
struct IntuiMessage *Message;
struct MsgPort *TimerPort;
struct timerequest *TimeReq;

char av[250],alert[110],tm2[10],a2[40]={ 1,1,105,67,
		"DigiZ a été créé par Mikaël Zajac",'\0'};
BOOL late=FALSE,wb2,win2=FALSE,reb;
int d=1,l=0,duree=15;

struct temps
{
	int sec,min,hr,mic;
};


void init()
{
	ULONG lock;
	if((IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0))==NULL) fin(1);
	if((TimerPort=(struct MsgPort *)CreatePort(0,0))==NULL) fin(2);
	if((TimeReq=(struct timerequest *)CreateExtIO(TimerPort,sizeof(struct timerequest)))==NULL) fin(3);
	if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimeReq,NULL)!=0) fin(4);
	lock=LockIBase(0);
	screen=IntuitionBase->FirstScreen;
	wb2=(IntuitionBase->LibNode.lib_Version>=37);
	if(wb2)
		NewWindow.Width=127;
	else
		NewWindow.IDCMPFlags=NewWindow.IDCMPFlags|ACTIVEWINDOW|INACTIVEWINDOW;
	UnlockIBase(lock);
	ascreen=screen;
}

int fin(l)
int l;
{
	switch(l)
	{
		case 4:	CloseDevice(TimeReq);
		case 3:	DeleteExtIO(TimeReq);
		case 2:	DeletePort(TimerPort);
		case 1:	CloseLibrary(IntuitionBase);
			break;
	}
	exit(0);
	return(0);
}

void ffen()
{
	CloseWindow(Window);
	Window=NULL;
}

void stop()
{
	if( !CheckIO(TimeReq) )
	 	AbortIO(TimeReq);
	WaitIO(TimeReq);  
}

void fenetre2()
{
	NewWindow2.Screen=screen;
	NewWindow2.TopEdge=(screen->Height-87)/2;
	NewWindow2.LeftEdge=(screen->Width-300)/2;
	if((Window2=(struct Window *)OpenWindow(&NewWindow2))==NULL)
	{
		stop();
		ffen();
		fin(4);
	}
	if(wb2)
		ModifyIDCMP(Window,MOUSEBUTTONS);
	else
		ModifyIDCMP(Window,ACTIVEWINDOW|INACTIVEWINDOW);
	PrintIText(Window2->RPort,&IText6,4,11); 
}
	
void ffen2()
{
	if(wb2)
		ModifyIDCMP(Window,CLOSEWINDOW|MOUSEBUTTONS);
	else
		ModifyIDCMP(Window,CLOSEWINDOW|MOUSEBUTTONS|ACTIVEWINDOW|INACTIVEWINDOW);
	CloseWindow(Window2);
	Window2=NULL;
}

int fenetre()        /* €‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ */
{
	if (screen==NULL) screen=ascreen;
	NewWindow.Screen=screen;
	NewWindow.LeftEdge=screen->Width-200;
	if((Window=(struct Window *)OpenWindow(&NewWindow))==NULL)
		fin(4);
	RPort=Window->RPort;
	ScreenToFront(screen);
	if(win2)
	{
		win2=FALSE;
		fenetre2();
	}
	return(0);
}

struct temps *Heure()
{
	struct temps *h;
	h=(struct temps *) malloc(sizeof(struct temps));
	TimeReq->tr_node.io_Command=TR_GETSYSTIME;
	DoIO(TimeReq);
	h->sec=TimeReq->tr_time.tv_secs;
	h->min=h->sec/60;
	h->hr=h->min/60;
	h->min%=60;
	h->hr%=24;
	h->sec%=60;
	h->mic=TimeReq->tr_time.tv_micro;
	return(h);
}
	

void launchtimer(l)
int l;
{
	struct temps *h;
	h=Heure();
	TimeReq->tr_node.io_Command=TR_ADDREQUEST;
	TimeReq->tr_time.tv_secs=(1000000-h->mic)/1000000;
	TimeReq->tr_time.tv_micro=(1000000-h->mic)%1000000;
	if(l==0) TimeReq->tr_time.tv_secs+=(59-h->sec);
	SendIO(TimeReq);
	free(h); 
}

void MakeAlertMsg()
{
	int i,j;
	alert[0]=0;
	alert[1]=95;
	alert[2]=37;
	for(i=0;themsgSIBuff[i]!='\0';alert[i+3]=themsgSIBuff[i],i+=1);
	alert[i+3]='\0';
	for(j=0;a2[j]!='\0';i+=1,alert[i+3]=a2[j],j+=1);
}

BOOL conforme(max,adr)
int max;
struct StringInfo *adr;
{
	return( (BOOL) conf(max,adr->LongInt));
}

BOOL rebours()
{
	BOOL Late=FALSE;
	struct temps *h;
	h=Heure();
	if((h->hr*3600+h->min*60+h->sec*l-(secSInfo.LongInt*l+minSInfo.LongInt*60+heureSInfo.LongInt*3600)<duree*50) && (onoff.Flags & SELECTED))
		Late=TRUE;
	free(h);
	Delay(duree*50);
	return(Late);
}

struct temps *Time()
{
	struct temps *h;

	h=Heure();
	if(l==1)
	{
		sprintf(tm2,"%2d:%2d:%2d\0",h->hr,h->min,h->sec);
		tm2[0]=zero(tm2[0]);
		tm2[3]=zero(tm2[3]);
		tm2[6]=zero(tm2[6]);
	}
	if(!wb2)
	{
		MyIT.IText=&tm2[0];
		if(l==0)
		{
			sprintf(tm2,"%2d:%2d\0",h->hr,h->min);
			tm2[0]=zero(tm2[0]);
			tm2[3]=zero(tm2[3]);
		}
		DrawImage(RPort,&Image1,0,0);
		PrintIText(RPort,&MyIT,spc(l),1);
	}
	else
	{
		if(l==0)
		{
			sprintf(tm2," %2d:%2d\0",h->hr,h->min);
			tm2[1]=zero(tm2[1]);
			tm2[4]=zero(tm2[4]);
		}
		SetWindowTitles(Window,tm2,-1);
	}
	return(h);
}

BOOL fonction(g,l)
int g,l;
{
	BOOL Late=FALSE;
	ULONG lock;

	switch(g)
	{
		case 1:	ffen2();
			break;
		case 3: stop();
			ffen2();
			ffen();
			Late=rebours();
			lock=LockIBase(0);
			screen=IntuitionBase->FirstScreen;
			UnlockIBase(lock);
		case 2:
			if(Window2!=NULL) ffen2();
			if(Window!=NULL) ffen();	
			if(g==2)
			{
				lock=LockIBase(0);
				screen=ascreen->NextScreen;
				UnlockIBase(lock);
			}
			fenetre();
			fenetre2();
			if(g==2) stop();
			break;
	}
	return(Late);
}

void oops(Gad,SI)
struct Gadget *Gad;
struct StringInfo *SI;
{
	AutoRequest(Window, &my_body_text, NULL, &my_ok_text, NULL, NULL, 200, 50);
	strcpy(SI->Buffer,SI->UndoBuffer);
	SI->NumChars=strlen(SI->Buffer);
	SI->BufferPos=SI->NumChars;
	ActivateWindow(Window2);
	RefreshGadgets(&chscr,Window2,NULL);
	ActivateGadget(Gad,Window2,NULL);
}

void fantom()
{
	onoff.Flags=GADGHBOX;
	heure.Flags=GADGHCOMP;
	min.Flags=GADGHCOMP;
	if(mode.Flags & SELECTED)
		sec.Flags=GADGHCOMP;
}


void Args(int argc, char **argv)
{
	int i=0,aa=0,bb=0,cc=0;
	struct WBStartup *WBS;
	
	char opt[9][5]={"-sec","-on","-@","-m","-h","?","-fen","-w","-d"},
	     opt2[7][9]={"SEC","ALARME","MSG","HEURE","FENETRE","DUREE","ATTENDRE"},*Value;
	BOOL muet=FALSE,Sec=FALSE,Alm=FALSE,Hr=FALSE;	

	
	if(argc!=0)
	{
		for(i=0;i<=argc-1;i+=1)
		{
			if(stricmp(argv[i],opt[0])==0) Sec=TRUE;
			
			if(stricmp(argv[i],opt[1])==0) Alm=TRUE;
			
			if(stricmp(argv[i],opt[2])==0)
				muet=TRUE;
			if(strnicmp(argv[i],opt[3],2)==0)
			{
				stccpy(themsgSIBuff,argv[i]+2,min(54,strlen(argv[i])-1));
				MakeAlertMsg();
			}
			if(strcmp(argv[i],opt[5])==0 &&_Backstdout)
			{
				Write(_Backstdout,Usage,sizeof(Usage));
				Write(_Backstdout,Usage2,sizeof(Usage2));
				Write(_Backstdout,Usage3,sizeof(Usage3));
				Write(_Backstdout,Usage4,sizeof(Usage4));
				Write(_Backstdout,Usage5,sizeof(Usage5));
				Write(_Backstdout,Usage6,sizeof(Usage6));
				Write(_Backstdout,Usage7,sizeof(Usage7));
				Write(_Backstdout,Usage8,sizeof(Usage8));
				Write(_Backstdout,Usage9,sizeof(Usage9));
				fin(0);
			}
			if(strnicmp(argv[i],opt[4],2)==0)
			{
				sscanf(argv[i],"-h%d%*c%d%*c%d",&aa,&bb,&cc);
				Hr=TRUE;
			}
			if(stricmp(opt[6],argv[i])==0) win2=TRUE;
			if(stricmp(opt[7],argv[i])==0) reb=TRUE;
			if(strnicmp(argv[i],opt[8],2)==0)
			{
				if(strlen(argv[i])>2) sscanf(argv[i],"-d%d",&duree);
			}
		}
	}
	else
	{
		WBS=(struct WBStartup *)argv;
		IconBase=(struct IconBase *)OpenLibrary(ICONNAME,0);
		if(IconBase!=NULL)
		{	
			DiskObj=GetDiskObject(WBS->sm_ArgList[0].wa_Name);
			if(DiskObj!=0)
			{
				Value=FindToolType(DiskObj->do_ToolTypes,opt2[0]);
				if(Value!=0) Sec=TRUE;
				Value=FindToolType(DiskObj->do_ToolTypes,opt2[1]);
				if(Value!=0) Alm=TRUE;
				Value=FindToolType(DiskObj->do_ToolTypes,opt2[2]);
				if(Value!=0)
				{
					stccpy(themsgSIBuff,Value,min(54,strlen(Value)+1));
					MakeAlertMsg();
				}
				Value=FindToolType(DiskObj->do_ToolTypes,opt2[3]);
				if(Value!=0)
				{
					sscanf(Value,"%d%*c%d%*c%d",&aa,&bb,&cc);
					Hr=TRUE;
				}
				Value=FindToolType(DiskObj->do_ToolTypes,opt2[4]);
				if(Value!=0) win2=TRUE;
				Value=FindToolType(DiskObj->do_ToolTypes,opt2[5]);
				if(Value!=0) sscanf(Value,"%d",&duree);
				Value=FindToolType(DiskObj->do_ToolTypes,opt2[6]);
				if(Value!=0) reb=TRUE;
				FreeDiskObject(DiskObj);
			} 
			CloseLibrary(IconBase); 
		}
	}

	if(Sec)
	{
		l=1;
		mode.Flags|=SELECTED;
		sec.Flags=GADGHCOMP;
	}
	if(Alm)
	{
		onoff.Flags|=SELECTED;
		min.Flags|=GADGDISABLED;
		heure.Flags|=GADGDISABLED;
		sec.Flags=GADGHCOMP|GADGDISABLED;
	}
	if(Hr)
		if (conf(24,aa) && conf(60,bb) && conf(60,cc))
		{
			heureSInfo.LongInt=aa;
			minSInfo.LongInt=bb;
			secSInfo.LongInt=cc;
			sprintf(heureSInfo.Buffer,"%d",aa);
			sprintf(minSInfo.Buffer,"%d",bb);
			sprintf(secSInfo.Buffer,"%d",cc);
			heureSInfo.NumChars=strlen(heureSInfo.Buffer);
			heureSInfo.BufferPos=heureSInfo.NumChars;
			minSInfo.NumChars=strlen(minSInfo.Buffer);
			minSInfo.BufferPos=minSInfo.NumChars;
			secSInfo.NumChars=strlen(secSInfo.Buffer);
			secSInfo.BufferPos=secSInfo.NumChars;
		}
		else
		{	if(argc!=0) Write(_Backstdout,hello,sizeof(hello));
			AutoRequest(NULL, &my_body_text, NULL, &my_ok_text, NULL, NULL, 200, 50);
			muet=TRUE;
		}
	
	if(_Backstdout && !muet && argc!=0)
		Write(_Backstdout,hello,sizeof(hello));
	if(_Backstdout)	Close(_Backstdout);
}


void main(int argc, char **argv)
{
	ULONG Class,seconds,micros,sec1=0,mic1=0,sec2=0,mic2=0;
	USHORT Code;
	long Sig;
	int k=0;
	APTR Address;

	BOOL closeme=FALSE,late=FALSE;
	struct temps *h;

	Args(argc,argv);

	init();
	if(reb) rebours();
	fenetre();
	free(Time());

	launchtimer(l);

	while(!closeme)
	{
		Sig=Wait(1<<Window->UserPort->mp_SigBit|1<<TimerPort->mp_SigBit|1<<Window2->UserPort->mp_SigBit);
		if(Sig & WSMask)
		{
			while(Message=(struct IntuiMessage *)
				GetMsg(Window->UserPort))
			{
				Class=Message->Class;
				Code=Message->Code;
				seconds = Message->Seconds;
      				micros  = Message->Micros;
				if(!wb2) Delay(1);
				ReplyMsg(Message);
				switch(Class)
				{
					case MOUSEBUTTONS:
						if( Code == MENUDOWN )
               					{
							sec2 = sec1;
		 					mic2 = mic1;
							sec1 = seconds;
							mic1 = micros;
							if( DoubleClick( sec2, mic2, sec1, mic1 ) && Window2==NULL )
							{
								sec1 = 0;
								mic1 = 0;
								fenetre2();
							}
						}
						break;
					case CLOSEWINDOW:
						closeme=TRUE;
						break;
				}
			}
			if(!wb2) stop();
		}
		if((Sig & W2SMask) && Window2!=NULL)
		{
			while(Message=(struct IntuiMessage *)
				GetMsg(Window2->UserPort))
			{
				Class=Message->Class;
				Code=Message->Code;
				Address=Message->IAddress;
				ReplyMsg(Message);
				if(Class==GADGETUP)
				{
					k=0;
					if(Address==(APTR) &heure)
						if(conforme(24,&heureSInfo))
							ActivateGadget(&min,Window2,NULL);
						else
							oops(&heure,&heureSInfo);
					if(Address==(APTR) &min)
						if(conforme(60,&minSInfo))
						{
							if(mode.Flags & SELECTED)  ActivateGadget(&sec,Window2,NULL);
						}
						else
							oops(&min,&minSInfo);
							
					if(Address==(APTR) &sec)
						if(!conforme(60,&secSInfo))
							oops(&sec,&secSInfo);
					if(Address==(APTR) &onoff)
						if(onoff.Flags & SELECTED)
						{
							OffGadget(&heure,Window2,NULL);
							OffGadget(&min,Window2,NULL);
							OffGadget(&sec,Window2,NULL);
						}
						else
						{
							OnGadget(&heure,Window2,NULL);
							OnGadget(&min,Window2,NULL);
							if(mode.Flags & SELECTED)
								OnGadget(&sec,Window2,NULL);
						}

					if(Address==(APTR) &mode)
					{
						l=abs(l-1);
						if(mode.Flags & SELECTED)
						{ 
							if(!(onoff.Flags & SELECTED))
								OnGadget(&sec,Window2,NULL);
							if(l) stop();
						}
						else
						{
							stop();
							MyIT.IText="        ";
							if(!wb2) PrintIText(RPort,&MyIT,30,1);
							OffGadget(&sec,Window2,NULL);
						}
					}
					if(Address==(APTR) &cntdwn)
						k=3;
					if(Address==(APTR) &chscr)
						k=2;
					if(Address==(APTR) &OK)
						k=1;
				}
			}
		}
		if(k!=0) 
		{
			late=fonction(k,l);
			k=0;
		}

		if(TimeSigMask & Sig)
		{
			h=Time();
			if(((h->hr*3600+h->min*60+h->sec==(secSInfo.LongInt+minSInfo.LongInt*60+heureSInfo.LongInt*3600)) && (onoff.Flags & SELECTED)) || late)
			{			
				late=FALSE;
				MakeAlertMsg();
				DisplayBeep(screen);
				DisplayAlert(DEADEND_ALERT,alert,75);
				if(Window2!=NULL)
				{
					ffen2();
					fantom();
					fenetre2();
				}
				else
					fantom();
			}
			launchtimer(l);
			free(h);
		}
	}
	stop();
	ffen();
	fin(4);
}
