  /* Fichier clock.dark.c				*/
/* Module appele par le programme principal	*/
/* pour effectuer un effet defini..appele par	*/
/* loadseg					*/

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <intuition/gadgetclass.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <dos/dos.h>
#include <graphics/gfxmacros.h>
#include <graphics/rastport.h>
#include <graphics/displayinfo.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/diskfont_protos.h>

#include "/includes/struct.h"
#include "/includes/tom_gadget.h"

struct Library		*DiskfontBase;
extern  struct  GfxBase *GfxBase;
struct TextFont *myfont;

#define	VOID_ARG	void	__regargs

char	*p_text_info=
"   ClockV1.3\n"
"\n"
"Choose on of the three kind of clocks:\n"
"\n"
"- A digital (You can select his font)\n"
"- Aiguilles \n"
"- Modern\n"
"\n"
" SpeedX and SpeedY select the moving speed\n"
" of the clock. A speed of 0 for X and Y make\n"
" the clock don't move\n"
" (thanks to the great possibilites of screen\n"
" scrolling under WB2.x for this smooth scrool)\n\n"
"      March 1993\n"
"      By Thomas LANDSPURG";

WORD	areabuffer[25];
struct	AreaInfo	myarea;
struct	TmpRas	tmpras;

struct	RastPort	*rp;
struct	Screen		*s;
struct	TextAttr myta;
WORD	len,h;

#define	RAYON	80

#define	WIDTHV	640
#define HEIGHTV	256
#define	WIDTH	((RAYON+20)*4)
#define	HEIGHT	((RAYON+20)*2)

#define	EXTRAX	(WIDTHV-WIDTH)
#define	EXTRAY	(HEIGHTV-HEIGHT)

#define	WIDTHS	(WIDTHV+EXTRAX)
#define	HEIGHTS	(HEIGHTV+EXTRAY)

UWORD	chip null_pointer[]={0,0,0,0,0,0};
UWORD  ScreenColors[] = {
    0x000,
    0xFFF,
    0xFE2,
    0x68B,
    0xF90,
    0x0F0,
    0x00F,
    0xF0F,
    0x000 };

UWORD DriPens[] = {
	~0 };


struct	Rectangle	clip={0,0,WIDTHV,HEIGHTV};

struct NewScreen Screen= {
     0, 0, WIDTH, HEIGHT, 3,0,1,HIRES,CUSTOMSCREEN,NULL,NULL,NULL,NULL};

#define	CENTRE_X (RAYON+20)*2
#define	CENTRE_Y (RAYON+20)

#define	TAILLE_N    ((RAYON+20)*2)

struct NewWindow    Window = {
    (WIDTHS-WIDTH)/2,
    (HEIGHTS-HEIGHT)/2,
    WIDTH,
    HEIGHT,0,1,
    IDCMP_GADGETDOWN|IDCMP_GADGETUP|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|IDCMP_INTUITICKS,
/*    WFLG_SMART_REFRESH|WFLG_ACTIVATE,*/
    WFLG_SMART_REFRESH|WFLG_ACTIVATE|BORDERLESS,
    0l,0,0,0,0,5,5,-1,-1,CUSTOMSCREEN};

UBYTE         *TypeLabels[] = {
    "Digital",
    "Normal",
    "Modern",
    0l };

struct	TextAttr myta={"topaz                    ",0,0,0};
struct	tom_gadget	my_gadg[]={
	{"Type",	MX,	167,14,17,30,0, 0,0,0,(char *)TypeLabels},
	{"_seconds",	CHECKBOX,160, 46, 100,40,0,0,0,0,0},
	{"_Fonts",	FONT,    160, 66, 80,12,0,0,0,0,(char *)&myta},
	{"Speed_X",	SLIDER,	 160, 80, 80,10,1,0,6,0,0},
	{"Speed_Y",	SLIDER,	 160, 95, 80,10,1,0,6,0,0},
	{0,		END_LISTE,  0,  0,   0, 0, 0,0,0,0,0}};

static	short	int	cos[360]={
256,255,255,255,255,255,254,254,
253,252,252,251,250,249,248,247,
246,244,243,242,240,238,237,235,
233,232,230,228,226,223,221,219,
217,214,212,209,207,204,201,198,
196,193,190,187,184,181,177,174,
171,167,164,161,157,154,150,146,
143,139,135,131,127,124,120,116,
112,108,104,100,95,91,87,83,
79,74,70,66,61,57,53,48,
44,40,35,31,26,22,17,13,
8,4,0,-4,-8,-13,-17,-22,
-26,-31,-35,-40,-44,-48,-53,-57,
-61,-66,-70,-74,-79,-83,-87,-91,
-95,-100,-104,-108,-112,-116,-120,-124,
-128,-131,-135,-139,-143,-146,-150,-154,
-157,-161,-164,-167,-171,-174,-177,-181,
-184,-187,-190,-193,-196,-198,-201,-204,
-207,-209,-212,-214,-217,-219,-221,-223,
-226,-228,-230,-232,-233,-235,-237,-238,
-240,-242,-243,-244,-246,-247,-248,-249,
-250,-251,-252,-252,-253,-254,-254,-255,
-255,-255,-255,-255,-256,-255,-255,-255,
-255,-255,-254,-254,-253,-252,-252,-251,
-250,-249,-248,-247,-246,-244,-243,-242,
-240,-238,-237,-235,-233,-232,-230,-228,
-226,-223,-221,-219,-217,-214,-212,-209,
-207,-204,-201,-198,-196,-193,-190,-187,
-184,-181,-177,-174,-171,-167,-164,-161,
-157,-154,-150,-146,-143,-139,-135,-131,
-127,-124,-120,-116,-112,-108,-104,-100,
-95,-91,-87,-83,-79,-74,-70,-66,
-61,-57,-53,-48,-44,-40,-35,-31,
-26,-22,-17,-13,-8,-4,0,4,
8,13,17,22,26,31,35,40,
44,48,53,57,61,66,70,74,
79,83,87,91,95,100,104,108,
112,116,120,124,128,131,135,139,
143,146,150,154,157,161,164,167,
171,174,177,181,184,187,190,193,
196,198,201,204,207,209,212,214,
217,219,221,223,226,228,230,232,
233,235,237,238,240,242,243,244,
246,247,248,249,250,251,252,252,
253,254,254,255,255,255,255,255
};
static	short	int	centre_x,centre_y,old_x,old_y,rayon;
static	int	old_min,old_hour,old_sec;

VOID_ARG	aff_line(struct	RastPort	*rp,
		short	int	cx,
		short	int	cy,
		short	int	sx,
		short	int	sy,
		USHORT		angle)
{
	short	int	x,y;
	unsigned	short	int	angle_sin;
	angle=angle%360;
	angle_sin=(angle+360-90)%360;
	x=sx*cos[angle]-sy*cos[angle_sin];
	y=sy*cos[angle]+sx*cos[angle_sin];
	Draw(rp,cx+2*x/256,cy-y/256);

}

VOID_ARG	aff_aguille(struct	RastPort	*rp,
		short	int	size,
		USHORT		angle)
{
	short		int	d;
	unsigned	short	int	ang;

	ang=(360-angle)%360;
	d=size/10;
	Move(rp,centre_x,centre_y);
	aff_line(rp,centre_x,centre_y,-d,size-d,ang);
	aff_line(rp,centre_x,centre_y,0,size,ang);
	aff_line(rp,centre_x,centre_y,d,size-d,ang);
	Draw(rp,centre_x,centre_y);
}

VOID_ARG	aff_aguille_sec(struct	RastPort	*rp,
		short	int	size,
		USHORT		angle)
{
	short		int	d;
	unsigned	short	int	ang;

	ang=(360-angle)%360;
	d=size/10;
	Move(rp,centre_x,centre_y);
	aff_line(rp,centre_x,centre_y,0,size,ang);
	Move(rp,centre_x,centre_y);
	ang=(ang+180)%360;
	aff_line(rp,centre_x,centre_y,0,size/10,ang);
}

VOID_ARG	aff_aguille_pleine(struct	RastPort	*rp,
			short	int	size,
			short	int	div,
			USHORT		angle)
{
	short	int	x1,y1,x2,y2;

	x1=size*cos[(angle+360-90)%360];
	y1=size*cos[(angle+360-180)%360];
	x2=(x1)/div;
	y2=(y1)/div;
	x1>>=8;
	y1>>=8;
	x2>>=8;
	y2>>=8;

	AreaMove(rp,centre_x+2*y2,centre_y-x2);
/*	AreaDraw(rp,centre_x+2*(y2+x1),centre_y-x2+y1);*/
/*	AreaDraw(rp,centre_x+2*(-y2+x1),centre_y+x2+y1);*/

	AreaDraw(rp,centre_x+2*x1,centre_y+y1);

	AreaDraw(rp,centre_x-2*y2,centre_y+x2);
	AreaEnd(rp);
}

VOID_ARG	aff_time(struct	Window	*win)
{
   struct	RastPort	*rp;
   int	seconds,minutes,hours;
   char		buffer[40];
   WORD	x,y;
   struct	DateStamp	now;
   static	WORD	old_len=0;
   static	WORD	new_len=0;

   DateStamp(&now) ;

   seconds=(int)(now.ds_Tick/TICKS_PER_SECOND);


   if(seconds!=old_sec){

	rp=win->RPort;
	minutes = now.ds_Minute % 60 ;
	hours = now.ds_Minute / 10 ;	/* Je divise par 6 tt a l'heure */


	switch(my_gadg[0].value){
	    case 0:
		x=(win->Width-len)/2;
		y=(win->Height/2-myfont->tf_YSize)+myfont->tf_Baseline;
		if(my_gadg[1].value!=FALSE){
			SPrintF(buffer,"%02ld:%02ld:%02ld",hours/6,minutes,seconds);
			new_len=TextLength(rp,buffer,strlen(buffer));

			Move(rp,x,y);
			Text(rp,buffer,2+2+2+2);
		}else{
			if(old_min!=minutes){
				SPrintF(buffer,"%02ld:%02ld",hours/6,minutes);
				new_len=TextLength(rp,buffer,strlen(buffer));
				Move(rp,x,y);
				Text(rp,buffer,2+2+1);
			}
		}
		/* Effacement de ce qui depasse, car fonte proportionelle */
		if(new_len<old_len){
			SetAPen(rp,0);
			RectFill(rp,x+new_len,y-myfont->tf_Baseline,x+old_len,y+myfont->tf_YSize-myfont->tf_Baseline);
			SetAPen(rp,1);
		}
		old_len=new_len;
		old_sec=seconds;
		old_min=minutes;
		break;
	    case 1:
		SetDrMd(rp,JAM2);

		if( ( (old_sec!=seconds)&&(my_gadg[1].value!=FALSE))||
		    ( (old_min!=minutes)&&(my_gadg[1].value==FALSE))){

			SetDrMd(rp,COMPLEMENT);
			SetAPen(rp,2);

			if(my_gadg[1].value){
				if(old_sec!=-1){
					aff_aguille_sec(rp,rayon-10,360*old_sec/60);
				}
				aff_aguille_sec(rp,rayon-10,360*seconds/60);
				old_sec=seconds;	
			}

			if(minutes!=old_min){
				SetAPen(rp,3);
				if(old_min!=-1){
					aff_aguille(rp,rayon-10,360*old_min/60);
				}
				old_min=minutes;
				aff_aguille(rp,rayon-10,360*old_min/60);
			}

			if(hours!=old_hour){
				SetAPen(rp,2);
				if(old_hour!=-1){
					aff_aguille(rp,rayon-30,(360*old_hour/(12*6))%360);
				}
				old_hour=hours;
				aff_aguille(rp,rayon-30,(360*old_hour/(12*6))%360);
			}
		}

		break;
	    case 2:

		SetAPen(rp,3);
		SetDrMd(rp,JAM2);

		if( ( (old_sec!=seconds)&&(my_gadg[1].value!=FALSE))||
		    ( (old_min!=minutes)&&(my_gadg[1].value==FALSE))){

			SetAPen(rp,1);
			if((old_hour!=-1)&&(old_hour!=hours)){
				aff_aguille_pleine(rp,rayon-30,5,(360*old_hour/(12*6))%360);
			}
			if((old_min!=-1)&&(old_min!=minutes)){
				aff_aguille_pleine(rp,rayon-15,8,360*old_min/60);
			}
			if(old_sec!=-1){
				aff_aguille_pleine(rp,rayon-10,20,360*old_sec/60);
			}

			old_hour=hours;
			SetAPen(rp,6);
			aff_aguille_pleine(rp,rayon-30,5,(360*old_hour/(12*6))%360);

			old_min=minutes;
			SetAPen(rp,7);
			aff_aguille_pleine(rp,rayon-15,8,360*old_min/60);

			if(my_gadg[1].value!=FALSE){
				SetAPen(rp,5);
				aff_aguille_pleine(rp,rayon-10,20,360*seconds/60);
				old_sec=seconds;
			}

		}

		break;
	}
   }
}


VOID_ARG	init_clock(struct	Window	*win)
{
	short	int	i,x,y;
	centre_x=win->Width/2;
	centre_y=win->Height/2;
	centre_x=CENTRE_X;
	centre_y=CENTRE_Y;
	rayon=RAYON;
	old_x=0;
	old_y=0;
	old_min=-1;
	old_hour=-1;
	old_sec=-1;

	switch(my_gadg[0].value){
	    case 0:
		if(DiskfontBase&&(myta.ta_Name!=0)){
                    if (myfont = OpenDiskFont(&myta))
                    {
	                    SetFont(rp, myfont);
                            SetSoftStyle(rp,   myta.ta_Style ^ myfont->tf_Style,
                                      (FSF_BOLD | FSF_UNDERLINED | FSF_ITALIC));
		    }
		}
		if(myta.ta_Name!=0){
			h=myta.ta_YSize;
		}else{
			h=8;
		}
		h+=10;
		len=TextLength(rp,"00:00:00",9);
/*		SizeWindow(win,-(win->Width-len),-(win->Height-h));*/
		SetAPen(rp,1);
		break;
	    case 1:
		SetAPen(win->RPort,3);
		SetDrMd(win->RPort,JAM2);
		SetAPen(win->RPort,4);
		for(i=0;i<12*3;i++){
			x=(rayon+10)*cos[(i*(360/12))%360];
			y=(rayon+10)*cos[(i*(360/12)+90)%360];
			Move(win->RPort,centre_x+2*x/256,centre_y+y/256);
			x=(x*9)/10;
			y=(y*9)/10;
			Draw(win->RPort,centre_x+2*x/256,centre_y+y/256);
		}
		break;
	    case 2:
		SetDrMd(win->RPort,JAM2);
		SetAPen(win->RPort,3);
		AreaMove(win->RPort,centre_x,centre_y);
		AreaEllipse(win->RPort,centre_x,centre_y,(rayon+10)*2,rayon+10);
		DrawEllipse(win->RPort,centre_x,centre_y,(rayon+10)*2,rayon+10);
		AreaEnd(win->RPort);

		SetAPen(win->RPort,1);
		AreaMove(win->RPort,centre_x,centre_y);
		AreaEllipse(win->RPort,centre_x,centre_y,(rayon-10)*2,rayon-10);
		AreaEnd(win->RPort);
		DrawEllipse(win->RPort,centre_x,centre_y,(rayon-10)*2,rayon-10);
		break;
	}
}

void	dark()
{
   struct	IntuiMessage	*msg;
   ULONG		class,depth;
   struct	Window	*w_time;
   int		tx,ty,x,y,dirx,diry;

/*
   switch(my_gadg[0].value){
	case 0:
	case 1:
		depth=2;
		break;
	case 2:
		depth=3;
		break;
   }
   Screen.Depth=depth;
*/
   if (  s = OpenScreenTags( NULL, SA_Left,	-EXTRAX/2,
				   SA_Top,	-EXTRAY/2,
				   SA_Width,	WIDTHS,
				   SA_Height,	HEIGHTS,
				   SA_Depth,	3,
				   SA_DClip,	&clip,
/*				   SA_Colors,	&ScreenColors[0],*/
				   SA_Type,	CUSTOMSCREEN,
				   SA_DisplayID,HIRES_KEY,
				   SA_Pens,	&DriPens[0],
				   SA_Title,	"Time....",
				   TAG_DONE )){

	rp = &(s->RastPort);

	SetRast(rp,0);
	Window.Screen=s;
	LoadRGB4(&s->ViewPort,ScreenColors,1<<3);

	if (  w_time = OpenWindow(&Window )){
		SetPointer( w_time, null_pointer, 1, 1, 0, 0);
		FreeSprite (0);
		GfxBase->SpriteReserved|=1;
		rp=w_time->RPort;
		InitArea(&myarea,areabuffer,10);
		rp->AreaInfo=&myarea;
		rp->TmpRas=(struct TmpRas *)InitTmpRas(&tmpras,AllocRaster(WIDTH,HEIGHT),RASSIZE(WIDTH,HEIGHT));
	
		init_clock(w_time);

		dirx=my_gadg[3].value;
		diry=my_gadg[4].value;
		x=EXTRAX/2;
		y=EXTRAY/2;
		tx=WIDTH;
		ty=HEIGHT;

		while(tst_end()==FALSE){

			x-=dirx;
			y-=diry;
			if(x-dirx<=0){
				dirx=-dirx;
			}
			if(y-diry<=0){
				diry=-diry;
			}
			if(x-dirx+tx>=WIDTHV){
				dirx=-dirx;
			}
			if(y-diry+ty>=HEIGHTV){
				diry=-diry;
			}
			/* Make screen moving only if dirx AND dir y are<>0 */
			/* If no, we make a WaitPort, wich is better to	    */
			/* take less CPU				    */
			if((dirx!=0)||(diry!=0)){
				MoveScreen( s,-dirx,-diry );
				WaitTOF();
			}else{
				WaitPort(w_time->UserPort);
			}
			while((msg=(struct IntuiMessage *)GetMsg(w_time->UserPort))!=0){
				class=msg->Class;
				ReplyMsg((struct Message *)msg);
				switch(class){
					case	INTUITICKS:
						aff_time(w_time);
						break;

					case	REFRESHWINDOW:
						init_clock(w_time);
						break;
					default:
						break;
				}
			}
		}
	}
	if ( w_time)CloseWindow( w_time );
	FreeRaster(tmpras.RasPtr,WIDTH,HEIGHT);
	DCloseScreen(s);
   }
}

void	proc_init()
{
        DiskfontBase = OpenLibrary("diskfont.library", 37L);
}

void	proc_save()
{
}
void	proc_end()
{
	if(DiskfontBase)CloseLibrary(DiskfontBase);
}

