/***********************/
/*  Skandalfo's Clock  */
/*---------------------*/
/* See AmigaGuide doc  */
/* for Copyright and   */
/* Licence.            */
/***********************/

#define VERSION "1.0"

#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/locale.h>
#include <libraries/gadtools.h>
#include <libraries/screennotify.h>
#include <proto/intuition.h>
#include <dos/dos.h>
#include <dos/datetime.h>
#include <proto/dos.h>
#include <exec/exec.h>
#include <proto/exec.h>
#include <workbench/startup.h>
#include <proto/icon.h>
#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <graphics/displayinfo.h>
#include <proto/graphics.h>
#include <datatypes/datatypes.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>
#include <datatypes/soundclass.h>
#include <proto/screennotify.h>
#include <proto/datatypes.h>
#include <devices/timer.h>
#include <proto/timer.h>
#include <proto/gadtools.h>
#include <proto/locale.h>

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/****************/
/* GLOBLAL VARS */
/****************/

#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef max
#define max(a,b) (((a)>(b))?(a):(b))
#endif
#define sgn(a) (((a)>0)?1:-1)

static char versionstring[]="$VER: SkandalfoClock " VERSION " " __AMIGADATE__;

struct Screen *sc=NULL;
struct Window *wi=NULL;
struct DrawInfo *di=NULL;
struct ExtGadget *ga,*db=NULL,*sg=NULL;
APTR gr=NULL,sr=NULL;

struct RastPort rpbackgd,rpbuffer;
struct BitMap *backgd=NULL,*buffer=NULL,*remapped=NULL,*trans=NULL;

struct TmpRas tmpras,tr2;
UBYTE *tmprasbuf=NULL;

struct AreaInfo areainfo,ai2;
#define MAXVECTORS 100
char areabuf[5*MAXVECTORS];

Object *dto=NULL;
struct dtFrameBox dtf;
struct FrameInfo fri;
struct gpLayout gpl;
struct BitMapHeader *bmh;

char psname[257]="Workbench";

Object *hso=NULL,*qso=NULL,*aso=NULL;
char hsfn[257]="",qsfn[257]="",asfn[257]="";
enum chimestype
{
	CNONE,CSINGLE,CMULTIPLE
} chimestype=CNONE;

int co[60],si[60];
int co2[60],si2[60];

enum windowtype
{
	WNORMAL,WBACKDROP
} windowtype=WNORMAL;
enum bordertype 
{
	BNONE, BSINGLE, BDOUBLE
} bordertype=BDOUBLE;

enum borderlook
{
	BNORMAL, BRECESSED
} borderlook=BNORMAL;

enum backtype
{
	BCOLOUR,BIMAGE,BTRANSPARENT
} backtype=BCOLOUR;

BOOL oval=FALSE;
BOOL seconds=TRUE;

enum showwhat
{
   	SWNOTHING,SWTWELVE,SWQUARTERS,SWHOURS,SWMINUTES
} showwhat=SWHOURS;

char backimage[257]="";

int borderwidth=1;

int borderheight=1;

BOOL windowadjustable=TRUE;
BOOL sizeaspicture=FALSE;

int windowleftedge=0;
int windowtopedge=0;
int windowwidth=100;
int windowheight=100;

int buffw=0,buffh=0;
int transw=0,transh=0;
int transcounter=0;

BOOL wpactive=FALSE;

int *hour,*minute,*second;
int *twelve,*quarters,*hours,*minutes;

struct colour
{
	enum colourtype
	{
		INDEX,RGB
	} type;
	int index;
	int R,G,B;
};

struct colour backcolour=
{
	INDEX,0,0,0,0
};

struct colour hour1=
{
	INDEX,1,0,0,0
},minute1=
{
	INDEX,1,0,0,0
},second1=
{
	INDEX,-1,0,0,0
},twelve1=
{
	INDEX,2,0,0,0
},quarters1=
{
	INDEX,2,0,0,0
},hours1=
{
	INDEX,1,0,0,0
},minutes1=
{
	INDEX,3,0,0,0
};

struct colour hour2=
{
	INDEX,3,0,0,0
},minute2=
{
	INDEX,3,0,0,0
},second2=
{
	INDEX,-1,0,0,0
},twelve2=
{
	INDEX,1,0,0,0
},quarters2=
{
	INDEX,1,0,0,0
},hours2=
{
	INDEX,1,0,0,0
},minutes2=
{
	INDEX,3,0,0,0
};

char hourf[257]="PROGDIR:data/hour.fig",
     minutef[257]="PROGDIR:data/minute.fig",
     secondf[257]="PROGDIR:data/second.fig",
     twelvef[257]="PROGDIR:data/twelve.fig",
     quartersf[257]="PROGDIR:data/quarters.fig",
     hoursf[257]="PROGDIR:data/hours.fig",
     minutesf[257]="PROGDIR:data/minutes.fig";

#define MENU_ABOUT			1
#define MENU_QUIT			2
#define MENU_ALARMSWITCH	3
#define MENU_ALARMSET		4
#define V(X)				(void *)X

struct NewMenu scmenu[]=
{
	
	{
		NM_TITLE,	"Project",		0,0,0,0
	},
	{
		NM_ITEM,	"About...",		"?",0,0,V(MENU_ABOUT)
	},
	{
		NM_ITEM,	"Quit",			"Q",0,0,V(MENU_QUIT)
	},
	{
		NM_TITLE,	"Settings",		0,0,0,0
	},
	{
		NM_ITEM,	"Alarm",		0,0,0,0
	},
	{
		NM_SUB,		"On",			0,CHECKIT,0,V(MENU_ALARMSWITCH)
	},
	{
		NM_SUB,		"Set...",		0,0,0,V(MENU_ALARMSET)
	},
	{
		NM_END,		0,				0,0,0,0
	}
};

APTR vi=NULL;
struct Menu *menu=NULL;

int alarmhours=0,alarmminutes=0,alarmcycles=1;
BOOL alarmon=FALSE;
BOOL alarmflag=FALSE;
struct Window *awi=NULL;
struct Gadget *glist=NULL,*slhoursgad,*slminutesgad,*textgad,*usegad,*cancelgad;
int awiiw,awiih;
char alarmstr[10];
			
#define ID_HOURS 69
#define ID_MINUTES 70
#define ID_TEXT 71
#define ID_USE 72
#define ID_CANCEL 73
			
/*******************/
/* END GLOBAL VARS */
/*******************/

/************************/
/* BEGIN LOCALE SUPPORT */
/************************/

struct Library *ScreenNotifyBase=NULL;
struct Library *LocaleBase=NULL;
struct Catalog *catalog=NULL;

enum localemsg
{
	MSG_PROJECT=0,
	MSG_ABOUT,
	MSG_ABOUTKEY,
	MSG_QUIT,
	MSG_QUITKEY,
	MSG_SETTINGS,
	MSG_ALARM,
	MSG_ON,
	MSG_SET,
	MSG_SETALARM,	
	MSG_HOURS,		
	MSG_MINUTES,	
	MSG_USE,		
	MSG_CANCEL,		
	MSG_ABOUTTEXT,	
	MSG_ABOUTBUTTON	
};

unsigned char *glstr(ULONG num, unsigned char *def)
{
    if(LocaleBase && catalog)
    {
        return GetCatalogStr(catalog,num,def);
    }
    else
        return def;
}

/**********************/
/* END LOCALE SUPPORT */
/**********************/

struct Gadget *CreateGads(void)
{
	struct Gadget *gad;
	struct NewGadget ng;
	struct RastPort rp;
	
	int buttonw,buttonh,labeloff;
	
	char *usestr=glstr(MSG_USE,"Use");
	char *cancelstr=glstr(MSG_CANCEL,"Cancel");
	char *hoursstr=glstr(MSG_HOURS,"Hours");
	char *minutesstr=glstr(MSG_MINUTES,"Minutes");
	
	/* di->dri_Font */
	/* sc->Font */
	
	InitRastPort(&rp);
	SetFont(&rp,di->dri_Font);
	
	/* TextLength(rp,str,count) */
	/* +12,+8 Buttons */
	/* +4,+4  Text    */
	/* 124,+0 Slider  */
	
	if(gad=CreateContext(&glist))
	{
		buttonw=12+max(TextLength(&rp,usestr,strlen(usestr)),TextLength(&rp,cancelstr,strlen(cancelstr)));
		buttonh=8+sc->Font->ta_YSize;
		labeloff=16+max(TextLength(&rp,hoursstr,strlen(hoursstr)),TextLength(&rp,minutesstr,strlen(minutesstr)));
		awiiw=max(labeloff+124+8,16+2*buttonw+8);
		awiih=4*sc->Font->ta_YSize+8+8+4+4+4+4;
		
		sprintf(alarmstr,"%02d:%02d",alarmhours,alarmminutes);
		
		ng.ng_TextAttr=sc->Font;
		ng.ng_VisualInfo=vi;
		ng.ng_LeftEdge=sc->WBorLeft+labeloff;
		ng.ng_TopEdge=sc->WBorTop+(sc->Font->ta_YSize)+4+1;
		ng.ng_Width=124;
		ng.ng_Height=sc->Font->ta_YSize;
		ng.ng_GadgetText=hoursstr;
		ng.ng_GadgetID=ID_HOURS;
		slhoursgad=gad=CreateGadget(SLIDER_KIND,gad,&ng,
									GTSL_MaxLevelLen,3,
									GTSL_MaxPixelLen,64,
									GTSL_Max,23,
									GTSL_Level,alarmhours,
									GA_RelVerify,TRUE,
									TAG_END);
									
		ng.ng_TopEdge=sc->WBorTop+(sc->Font->ta_YSize)*2+8+1;
		ng.ng_GadgetText=minutesstr;
		ng.ng_GadgetID=ID_MINUTES;
		slminutesgad=gad=CreateGadget(SLIDER_KIND,gad,&ng,
									GTSL_MaxLevelLen,3,
									GTSL_MaxPixelLen,64,
									GTSL_Max,59,
									GTSL_Level,alarmminutes,
									GA_RelVerify,TRUE,
									TAG_END);
		
		ng.ng_TopEdge=sc->WBorTop+(sc->Font->ta_YSize)*3+12+1;
		ng.ng_LeftEdge=sc->WBorLeft+8;
		ng.ng_GadgetText=NULL;
		ng.ng_GadgetID=ID_TEXT;
		ng.ng_Width=awiiw-16;
		ng.ng_Height=sc->Font->ta_YSize+4;
		textgad=gad=CreateGadget(TEXT_KIND,gad,&ng,
									GTTX_Border,TRUE,
									GTTX_Clipped,TRUE,
									GTTX_Justification,GTJ_CENTER,
									GTTX_Text,alarmstr,
									TAG_END);

		ng.ng_TopEdge=sc->WBorTop+(sc->Font->ta_YSize)*4+20+1;
		ng.ng_GadgetText=usestr;
		ng.ng_GadgetID=ID_USE;
		ng.ng_Width=buttonw;
		ng.ng_Height=buttonh;
		usegad=gad=CreateGadget(BUTTON_KIND,gad,&ng,
									TAG_END);

		ng.ng_LeftEdge=awiiw-8-buttonw+sc->WBorLeft;
		ng.ng_GadgetText=cancelstr;
		ng.ng_GadgetID=ID_CANCEL;
		cancelgad=gad=CreateGadget(BUTTON_KIND,gad,&ng,
									TAG_END);		
	}
	
	return gad;
}

void awiopen(void)
{
	struct Gadget *gad;
	
	if(awi)
		return;
	
	if(gad=CreateGads())
	{
		if(!(awi=OpenWindowTags(NULL,WA_PubScreen,sc,WA_InnerWidth,awiiw,WA_InnerHeight,awiih,
							WA_Gadgets,glist,
							WA_Flags,WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SIMPLE_REFRESH|WFLG_ACTIVATE|WFLG_NEWLOOKMENUS,
							WA_IDCMP,IDCMP_GADGETUP|IDCMP_REFRESHWINDOW,
							WA_Title,glstr(MSG_SETALARM,"Set Alarm"),TAG_DONE)))
		{
								FreeGadgets(glist);
		}
		else
		{
			GT_RefreshWindow(awi,NULL);
			
		}
	}
}

void awiclose(void)
{
	if(awi)
	{
		CloseWindow(awi);
		FreeGadgets(glist);
		awi=NULL;
	}
}

void updatetext(void)
{
	int h,m;
	
	GT_GetGadgetAttrs(slhoursgad,awi,NULL,GTSL_Level,&h,TAG_DONE);
	GT_GetGadgetAttrs(slminutesgad,awi,NULL,GTSL_Level,&m,TAG_DONE);
	
	sprintf(alarmstr,"%02d:%02d",h,m);
	GT_SetGadgetAttrs(textgad,awi,NULL,GTTX_Text,alarmstr);
}

void setpen(struct colour *col, char *s)
{
	if(*s=='#')
	{
		col->type=INDEX;
		col->index=atoi(s+1);
	}
	else
	{
		col->type=RGB;
		sscanf(s,"%d,%d,%d",&(col->R),&(col->G),&(col->B));
	}
}

void preparepen(struct colour *col)
{
	if(col->type==RGB)
	{
		col->index=ObtainBestPen(sc->ViewPort.ColorMap,(col->R)|(col->R<<8)|(col->R<<16)|(col->R<<24),(col->G)|(col->G<<8)|(col->G<<16)|(col->G<<24),(col->B)|(col->B<<8)|(col->B<<16)|(col->B<<24),TAG_DONE);
	}
}

void finishpen(struct colour *col)
{
	if(col->type==RGB)
	{
		ReleasePen(sc->ViewPort.ColorMap,col->index);
	}
}

#define drawfig(a,b) drawfigA(a,b,co,si,&rpbuffer)
#define drawfig2(a,b) drawfigA(a,b,co2,si2,&rpbuffer)
#define drawfig3(a,b) drawfigA(a,b,co,si,&rpbackgd)
#define drawfig4(a,b) drawfigA(a,b,co2,si2,&rpbackgd)

void drawfigA(int *fig, int a, int *co, int *si, struct RastPort *rpbuffer)
{
	int centerx,centery;
	int i,x,y,w,h;
	
	if(fig==NULL)
		return;
	
	w=bordertype+borderwidth*(bordertype==BDOUBLE);
	h=bordertype+borderheight*(bordertype==BDOUBLE);
	
	centerx=windowwidth/2-w;
	centery=windowheight/2-h;

	InitArea(&areainfo,areabuf,MAXVECTORS);

	i=fig[0]-1;
   	x=fig[1+2*i]*co[a]-fig[2+2*i]*si[a];
   	y=-fig[1+2*i]*si[a]-fig[2+2*i]*co[a];
   	x=(x*centerx)>>16;
   	y=(y*centery)>>16;
   	x+=centerx;
   	y+=centery;
   	AreaMove(rpbuffer,x+w,y+h);
	
	
	for(i=0;i<fig[0];i++)
	{
    	x=fig[1+2*i]*co[a]-fig[2+2*i]*si[a];
    	y=-fig[1+2*i]*si[a]-fig[2+2*i]*co[a];
    	x=(x*centerx)>>16;
    	y=(y*centery)>>16;
    	x+=centerx;
    	y+=centery;
    	AreaDraw(rpbuffer,x+w,y+h);
	}
	AreaEnd(rpbuffer);
}

int *readfig(char *name)
{
	FILE *f;
	int l=0;
	int a,b;
	int *p;
	int k;
	
	if(f=fopen(name,"r"))
	{
    	while(k=fscanf(f,"%d%d",&a,&b)==2)
    	{
    		l++;
    	}
    	fclose(f);
		if(f=fopen(name,"r"))
		{
			if(p=malloc((l*2+1)*sizeof(int)))
			{
				p[0]=l;
    			while(fscanf(f,"%d%d",&a,&b)==2 && l)
    			{
    				l--;
                    p[1+2*l]=a;
                    p[2+2*l]=b;
    			}
    			fclose(f);
    			return p;
    		}
    		fclose(f);
		}
	}
	return NULL;
}

void initbufferbackgd(void)
{
	int y;
	struct DateStamp ds;

	if(tmprasbuf)
	{
		FreeRaster(tmprasbuf,buffw,buffh);
		tmprasbuf=NULL;
	}

    Forbid();
    buffw=wi->Width;
    buffh=wi->Height;
    Permit();

	if(buffer)
	{
		FreeBitMap(buffer);
		buffer=NULL;
	}
	buffer=AllocBitMap(buffw,buffh,di->dri_Depth,BMF_CLEAR,wi->RPort->BitMap);

	tmprasbuf=AllocRaster(buffw,buffh);

	if(backgd)
	{
		FreeBitMap(backgd);
		backgd=NULL;
	}
	backgd=AllocBitMap(buffw,buffh,di->dri_Depth,BMF_CLEAR,buffer);
	
	InitTmpRas(&tmpras,tmprasbuf,RASSIZE(buffw,buffh));
	InitArea(&areainfo,areabuf,MAXVECTORS);
	InitTmpRas(&tr2,tmprasbuf,RASSIZE(buffw,buffh));
	InitArea(&ai2,areabuf,MAXVECTORS);
	
	rpbuffer.BitMap=buffer;
	rpbuffer.TmpRas=&tmpras;
	rpbuffer.AreaInfo=&areainfo;
	rpbackgd.TmpRas=&tr2;
	rpbackgd.AreaInfo=&ai2;
	rpbackgd.BitMap=backgd;
	
	switch(backtype)
	{
		case BCOLOUR:
   			SetRast(&rpbackgd,backcolour.index);
			break;
		case BIMAGE:
			if(trans)
			{
				int i,j;
				
				for(i=0;i<buffh;i+=transh)
					for(j=0;j<buffw;j+=transw)
		            	BltBitMap(trans,0,0,backgd,j,i,min(buffw-j,transw),min(buffh-i,transh),0x0C0,0xFF,NULL);
            }
			break;
		case BTRANSPARENT:
			if(trans)
			{
            	BltBitMap(trans,0,0,backgd,0,0,min(buffw,transw),min(buffh,transh),0x0C0,0xFF,NULL);
            }
			break;
	}
	
	if(oval)
	{
		if(showwhat>=SWTWELVE)
		{
			SetAPen(&rpbackgd,twelve1.index);
			SetOPen(&rpbackgd,twelve2.index);
			drawfig3(twelve,0);
		}
		if(showwhat>=SWQUARTERS)
		{
			SetAPen(&rpbackgd,quarters1.index);
			SetOPen(&rpbackgd,quarters2.index);
			drawfig3(quarters,15);
			drawfig3(quarters,30);
			drawfig3(quarters,45);
		}
		if(showwhat>=SWHOURS)
		{
			SetAPen(&rpbackgd,hours1.index);
			SetOPen(&rpbackgd,hours2.index);
			drawfig3(hours,5);
			drawfig3(hours,10);
			drawfig3(hours,20);
			drawfig3(hours,25);
			drawfig3(hours,35);
			drawfig3(hours,40);
			drawfig3(hours,50);
			drawfig3(hours,55);
		}
		if(showwhat>=SWMINUTES)
		{
			SetAPen(&rpbackgd,minutes1.index);
			SetOPen(&rpbackgd,minutes2.index);
			for(y=1;y<60;y++)
			{
				if(y%5)
				{
					drawfig3(minutes,y);
				}
			}
		}
	}
	else
	{
		if(showwhat>=SWTWELVE)
		{
			SetAPen(&rpbackgd,twelve1.index);
			SetOPen(&rpbackgd,twelve2.index);
			drawfig4(twelve,0);
		}
		if(showwhat>=SWQUARTERS)
		{
			SetAPen(&rpbackgd,quarters1.index);
			SetOPen(&rpbackgd,quarters2.index);
			drawfig4(quarters,15);
			drawfig4(quarters,30);
			drawfig4(quarters,45);
		}
		if(showwhat>=SWHOURS)
		{
			SetAPen(&rpbackgd,hours1.index);
			SetOPen(&rpbackgd,hours2.index);
			drawfig4(hours,5);
			drawfig4(hours,10);
			drawfig4(hours,20);
			drawfig4(hours,25);
			drawfig4(hours,35);
			drawfig4(hours,40);
			drawfig4(hours,50);
			drawfig4(hours,55);
		}
		if(showwhat>=SWMINUTES)
		{
			SetAPen(&rpbackgd,minutes1.index);
			SetOPen(&rpbackgd,minutes2.index);
			for(y=1;y<60;y++)
			{
				if(y%5)
				{
					drawfig4(minutes,y);
				}
			}
		}
	}

	ds.ds_Days=ds.ds_Minute=ds.ds_Tick=0;
	DateStamp(&ds);

	y=(ds.ds_Minute/12)%60;
	SetAPen(&rpbackgd,hour1.index);
	SetOPen(&rpbackgd,hour2.index);
	drawfig3(hour,y);

	y=ds.ds_Minute%60;
	SetAPen(&rpbackgd,minute1.index);
	SetOPen(&rpbackgd,minute2.index);
	drawfig3(minute,y);

}

void drawborder(void)
{
	int k,ac=0;
	struct RastPort *rp;
	
	rp=wi->RPort;
	
	SetDrMd(rp,JAM1);
	
	if(wi->Flags&WFLG_WINDOWACTIVE)
	{
		ac=1;
	}
	
	switch(bordertype)
	{
		case BNONE:
			break;
		case BSINGLE:
			k=borderlook^ac;
			if(k)
			{
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,0,0);
				Draw(rp,wi->Width-1,0);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,0,wi->Height-1);
				Draw(rp,wi->Width-1,wi->Height-1);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,0,0);
				Draw(rp,0,wi->Height-1);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,wi->Width-1,0);
				Draw(rp,wi->Width-1,wi->Height-1);
			}
			else
			{
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,0,0);
				Draw(rp,wi->Width-1,0);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,0,wi->Height-1);
				Draw(rp,wi->Width-1,wi->Height-1);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,0,0);
				Draw(rp,0,wi->Height-1);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,wi->Width-1,0);
				Draw(rp,wi->Width-1,wi->Height-1);				
			}
			break;
		case BDOUBLE:
			k=borderlook;
			if(k)
			{
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,0,0);
				Draw(rp,wi->Width-1,0);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,0,wi->Height-1);
				Draw(rp,wi->Width-1,wi->Height-1);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,0,0);
				Draw(rp,0,wi->Height-1);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,wi->Width-1,0);
				Draw(rp,wi->Width-1,wi->Height-1);

				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,1+borderwidth,1+borderheight);
				Draw(rp,wi->Width-2-borderwidth,1+borderheight);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,1+borderwidth,wi->Height-2-borderheight);
				Draw(rp,wi->Width-2-borderwidth,wi->Height-2-borderheight);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,1+borderwidth,1+borderheight);
				Draw(rp,1+borderwidth,wi->Height-2-borderheight);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,wi->Width-2-borderwidth,1+borderheight);
				Draw(rp,wi->Width-2-borderwidth,wi->Height-2-borderheight);				
			}
			else
			{
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,0,0);
				Draw(rp,wi->Width-1,0);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,0,wi->Height-1);
				Draw(rp,wi->Width-1,wi->Height-1);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,0,0);
				Draw(rp,0,wi->Height-1);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,wi->Width-1,0);
				Draw(rp,wi->Width-1,wi->Height-1);

				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,1+borderwidth,1+borderheight);
				Draw(rp,wi->Width-2-borderwidth,1+borderheight);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,1+borderwidth,wi->Height-2-borderheight);
				Draw(rp,wi->Width-2-borderwidth,wi->Height-2-borderheight);
				SetAPen(rp,di->dri_Pens[SHADOWPEN]);
				Move(rp,1+borderwidth,1+borderheight);
				Draw(rp,1+borderwidth,wi->Height-2-borderheight);
				SetAPen(rp,di->dri_Pens[SHINEPEN]);
				Move(rp,wi->Width-2-borderwidth,1+borderheight);
				Draw(rp,wi->Width-2-borderwidth,wi->Height-2-borderheight);				
			}
			
			if(ac)
			{
				SetAPen(rp,di->dri_Pens[FILLPEN]);
			}
			else
			{
				SetAPen(rp,di->dri_Pens[BACKGROUNDPEN]);
			}
			if(borderwidth)
			{
				RectFill(rp,1,1,borderwidth,wi->Height-2);
				RectFill(rp,wi->Width-1-borderwidth,1,wi->Width-2,wi->Height-2);
			}
			if(borderheight)
			{
				RectFill(rp,1,1,wi->Width-2,borderheight);
				RectFill(rp,1,wi->Height-1-borderheight,wi->Width-2,wi->Height-2);
			}
			
			break;
	}
}

void draw(BOOL refresh)
{
	int x,y,w,h;
	struct DateStamp ds;
	struct DateTime dati;
	
	static int lastminute=-1,nh=0,nq=0,lastday=-1;

	static char datebuf[160];
	char dn[32],dt[128];
	
	struct dtTrigger dtt=
	{
		DTM_TRIGGER,NULL,STM_PLAY,NULL
	};

	ds.ds_Days=ds.ds_Minute=ds.ds_Tick=0;
	DateStamp(&ds);

	if(ds.ds_Days!=lastday)
	{
		dati.dat_Stamp=ds;
		dati.dat_Format=4; /* Locale default? */
		dati.dat_Flags=0;
		dati.dat_StrDay=dn;
		dati.dat_StrDate=dt;
		dati.dat_StrTime=NULL;
		
		DateToStr(&dati);
		
		strcpy(datebuf,dn);
		strcat(datebuf,", ");
		strcat(datebuf,dt);
		
		SetWindowTitles(wi,NULL,datebuf);
		
		lastday=ds.ds_Days;
	}

	if(!alarmflag && alarmon && ds.ds_Minute==(alarmhours*60+alarmminutes))
	{
		alarmflag=TRUE;
		if(aso)
		{
			SetDTAttrs (aso, NULL, NULL, SDTA_Cycles, alarmcycles, TAG_END);
			DoDTMethodA (aso, NULL, NULL, (Msg)&dtt);
		}

	}
	if(alarmflag && ds.ds_Minute!=(alarmhours*60+alarmminutes))
	{
		alarmflag=FALSE;
	}

	y=ds.ds_Minute%60;

	if(lastminute>0 && chimestype==CMULTIPLE)
	{
		if(lastminute<15 && y>=15)
		{
			nq=1;
		}
		if(lastminute<30 && y>=30)
		{
			nq=2;
		}
		if(lastminute<45 && y>=45)
		{
			nq=3;
		}
		if(lastminute>=45 && y<15)
		{
			nq=4;
			nh=(ds.ds_Minute/60)%12;
			if(!nh) nh=12;
		}
		if(!qso) nq=0;
		if(!hso) nh=0;
	}

	if(lastminute>0 && chimestype==CSINGLE)
	{
		if(lastminute<15 && y>=15)
		{
			nq=1;
		}
		if(lastminute<30 && y>=30)
		{
			nq=1;
		}
		if(lastminute<45 && y>=45)
		{
			nq=1;
		}
		if(lastminute>=45 && y<15)
		{
			nh=1;
		}
		if(!qso) nq=0;
		if(!hso) nh=0;
	}

	if(nq && !((ds.ds_Tick/50)&1))
	{
		nq--;
		if(qso)
			DoDTMethodA (qso, NULL, NULL, (Msg)&dtt);
	}
	else if(nh && !((ds.ds_Tick/50)&1))
	{
		nh--;
		if(hso)
			DoDTMethodA (hso, NULL, NULL, (Msg)&dtt);
	}

	if(y!=lastminute)
	{
		initbufferbackgd();
	}

	if(!seconds && y==lastminute && !refresh)
	{
		return;
	}

	lastminute=y;

	BltBitMap(backgd,0,0,buffer,0,0,buffw,buffh,0x0C0,0xFF,NULL);
/*			
**	x=(ds.ds_Minute/12)%60;
**	SetAPen(&rpbuffer,hour1.index);
**	SetOPen(&rpbuffer,hour2.index);
**	drawfig(hour,x);
**
**	SetAPen(&rpbuffer,minute1.index);
**	SetOPen(&rpbuffer,minute2.index);
**	drawfig(minute,y);
*/
	if(seconds)
	{
		x=(ds.ds_Tick/50)%60;
		SetAPen(&rpbuffer,second1.index);
		SetOPen(&rpbuffer,second2.index);
		drawfig(second,x);
	}
	
	x=bordertype+borderwidth*(bordertype==BDOUBLE);
	y=bordertype+borderheight*(bordertype==BDOUBLE);
	w=buffw-2*x;
	h=buffh-2*y;
	BltBitMapRastPort(buffer,x,y,wi->RPort,x,y,w,h,0x0C0);
}

int wopen(void)
{
	if(backtype==BTRANSPARENT && trans)
	{
		FreeBitMap(trans);
		trans=NULL;
	}
	if(backtype==BTRANSPARENT)
	{
        trans=AllocBitMap(windowwidth,windowheight,di->dri_Depth,BMF_CLEAR,NULL);
        transw=windowwidth;
        transh=windowheight;
        if(trans)
        {
			if(wi=OpenWindowTags(NULL,	WA_Width,windowwidth,WA_Height,windowheight,WA_Title,NULL,WA_PubScreen,sc,
										WA_MinWidth,20,WA_MinHeight,20,WA_MaxWidth,65535,WA_MaxHeight,65535,
										WA_SizeGadget,FALSE,WA_DragBar,FALSE,WA_Borderless,TRUE,
										WA_Activate,FALSE,
										WA_BackFill,LAYERS_NOBACKFILL,WA_Backdrop,windowtype,
										WA_Left,windowleftedge,WA_Top,windowtopedge,
										TAG_DONE))
			{
			    BltBitMap(wi->RPort->BitMap,windowleftedge,windowtopedge,trans,0,0,windowwidth,windowheight,0x0C0,0xFF,NULL);
				CloseWindow(wi);
			}
			else
			{
				FreeBitMap(trans);
				trans=NULL;
			}
        }
	}
		
	if(wi=OpenWindowTags(NULL,	WA_Width,windowwidth,WA_Height,windowheight,WA_Title,NULL,WA_PubScreen,sc,
								WA_MinWidth,20,WA_MinHeight,20,WA_MaxWidth,65535,WA_MaxHeight,65535,
								WA_SizeGadget,windowadjustable,WA_DragBar,windowadjustable,WA_Borderless,TRUE,
								WA_Activate,wpactive,WA_SimpleRefresh,TRUE,
								WA_BackFill,LAYERS_NOBACKFILL,WA_Backdrop,windowtype,
								WA_NewLookMenus,TRUE,WA_IDCMP,IDCMP_NEWSIZE|IDCMP_CHANGEWINDOW|IDCMP_REFRESHWINDOW|IDCMP_VANILLAKEY|IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_MENUPICK,
								WA_Left,windowleftedge,WA_Top,windowtopedge,
								TAG_DONE))
	{
		wi->BorderLeft=wi->BorderRight=wi->BorderTop=wi->BorderBottom=0;
		
		Forbid();		
		ga=(struct ExtGadget *)wi->FirstGadget;
		
		db=sg=NULL;
		
		while(ga)
		{
			if(((ga->GadgetType)&(GTYP_SYSTYPEMASK))==(GTYP_WDRAGGING))
			{
				db=ga;
			}
			if(((ga->GadgetType)&(GTYP_SYSTYPEMASK))==(GTYP_SIZING))
			{
				sg=ga;
			}
			ga=ga->NextGadget;
		}
		if(db && sg)
		{
			db->Height=-sg->Height;
			db->Flags|=GFLG_RELHEIGHT;
		
			gr=sg->GadgetRender;
			sr=sg->SelectRender;
		
			sg->GadgetRender=NULL;
			sg->SelectRender=NULL;
		}
		Permit();
		
		if(backtype==BCOLOUR)
		{
			preparepen(&backcolour);
		}
		preparepen(&hour1);
		preparepen(&minute1);
		preparepen(&second1);
		preparepen(&twelve1);
		preparepen(&quarters1);
		preparepen(&hours1);
		preparepen(&minutes1);
		preparepen(&hour2);
		preparepen(&minute2);
		preparepen(&second2);
		preparepen(&twelve2);
		preparepen(&quarters2);
		preparepen(&hours2);
		preparepen(&minutes2);


		InitRastPort(&rpbuffer);
		InitRastPort(&rpbackgd);

		initbufferbackgd();
		drawborder();
		draw(TRUE);
		
		SetMenuStrip(wi,menu);
		
		return 1;
	}
	else
	{
		return 0;
	}
}

void wclose(void)
{
	if(tmprasbuf)
	{
		FreeRaster(tmprasbuf,buffw,buffh);
		tmprasbuf=NULL;
	}

	if(trans && backtype==BTRANSPARENT)
	{
		FreeBitMap(trans);
		trans=NULL;
	}
	if(backgd)
	{
		FreeBitMap(backgd);
		backgd=NULL;
	}
	if(buffer)
	{
		FreeBitMap(buffer);
		buffer=NULL;
	}

	if(backtype==BCOLOUR)
	{
		finishpen(&backcolour);
	}
	finishpen(&hour1);
	finishpen(&minute1);
	finishpen(&second1);
	finishpen(&twelve1);
	finishpen(&quarters1);
	finishpen(&hours1);
	finishpen(&minutes1);
	finishpen(&hour2);
	finishpen(&minute2);
	finishpen(&second2);
	finishpen(&twelve2);
	finishpen(&quarters2);
	finishpen(&hours2);
	finishpen(&minutes2);

	if(db && sg)
	{
		sg->GadgetRender=gr;
		sg->SelectRender=sr;
	}
	
	windowleftedge=wi->LeftEdge;
	windowtopedge=wi->TopEdge;
	windowwidth=wi->Width;
	windowheight=wi->Height;

	if(wi->Flags&WFLG_WINDOWACTIVE)
	{
		wpactive=TRUE;
	}
	else
	{
		wpactive=FALSE;
    }
    
    ClearMenuStrip(wi);
	CloseWindow(wi);
	wi=NULL;
	db=sg=NULL;
	gr=sr=NULL;
}

int main(int argc, char *argv[])
{
	int rc=20;
	BOOL running=TRUE,noexit=TRUE;
	struct IntuiMessage *im;
	
	struct MsgPort *tmp;
	struct timerequest *tior;
	
	ULONG signals;
	int a;

	struct MsgPort *snmp=NULL;
	APTR snhandle=NULL;
	struct ScreenNotifyMessage *snm=NULL;

	struct EasyStruct aboutes=
	{
		sizeof(struct EasyStruct),
		0,
		"SkandalfoClock "VERSION" "__AMIGADATE__,
		"Written by:\n  Juan J. García de Soria\n  c/ Alte. León Herrero 31, 5ºJ\n  11100 San Fernando (Cádiz)\n  SPAIN\n\nE-mail:\n  amisanf@ctv.es\n  soria@bart.us.es\n\nThis program is (E-MAIL|CARD)WARE:\nIf you use it please send the author\nan e-mail or postcard.",
		"Yes, Sir"
	};

	if(LocaleBase = OpenLibrary("locale.library",38))
	{
		catalog=OpenCatalog(NULL,"skandalfoclock.catalog",NULL);
	}

	aboutes.es_TextFormat=glstr(MSG_ABOUTTEXT,aboutes.es_TextFormat);
	aboutes.es_GadgetFormat=glstr(MSG_ABOUTBUTTON,aboutes.es_GadgetFormat);

	scmenu[0].nm_Label=glstr(MSG_PROJECT,scmenu[0].nm_Label);
	scmenu[1].nm_Label=glstr(MSG_ABOUT,scmenu[1].nm_Label);
	scmenu[2].nm_Label=glstr(MSG_QUIT,scmenu[2].nm_Label);
	scmenu[3].nm_Label=glstr(MSG_SETTINGS,scmenu[3].nm_Label);
	scmenu[4].nm_Label=glstr(MSG_ALARM,scmenu[4].nm_Label);
	scmenu[5].nm_Label=glstr(MSG_ON,scmenu[5].nm_Label);
	scmenu[6].nm_Label=glstr(MSG_SET,scmenu[6].nm_Label);

	scmenu[1].nm_CommKey=glstr(MSG_ABOUTKEY,scmenu[1].nm_CommKey);
	scmenu[2].nm_CommKey=glstr(MSG_QUITKEY,scmenu[2].nm_CommKey);

	{
		BPTR oldcd,pdcd;
		struct DiskObject *dobj;
		struct WBStartup *wbs;
		STRPTR s,t;
		char name[257];
		if(!argc)
		{
			wbs=(struct WBStartup *)argv;
			oldcd=CurrentDir(wbs->sm_ArgList->wa_Lock);
			strcpy(name,wbs->sm_ArgList->wa_Name);
		}
		else
		{
			s=argv[0];
			t=s;
			while(*s)
			{
				if(*s=='/' || *s==':')
				{
					t=s+1;
				}
				s++;
			}
			strcpy(name,t);
			pdcd=Lock("PROGDIR:",ACCESS_READ);
			oldcd=CurrentDir(pdcd);
		}
		
		if(dobj=GetDiskObject(name))
		{
			if(s=FindToolType(dobj->do_ToolTypes,"BACKDROP"))
			{
				windowtype=WBACKDROP;
			}
			if(s=FindToolType(dobj->do_ToolTypes,"BORDER"))
			{
				if(!strcmp(s,"NONE"))
				{
					bordertype=BNONE;
				}
				else if(!strcmp(s,"SINGLE"))
				{
					bordertype=BSINGLE;
				}
				else if(!strcmp(s,"DOUBLE"))
				{
					bordertype=BDOUBLE;
				}
			}
			if(s=FindToolType(dobj->do_ToolTypes,"CHIMES"))
			{
				if(!strcmp(s,"NONE"))
				{
					chimestype=CNONE;
				}
				else if(!strcmp(s,"SINGLE"))
				{
					chimestype=CSINGLE;
				}
				else if(!strcmp(s,"MULTIPLE"))
				{
					chimestype=CMULTIPLE;
				}
			}
			if(s=FindToolType(dobj->do_ToolTypes,"RECESSED"))
			{
				borderlook=BRECESSED;
			}
			if(s=FindToolType(dobj->do_ToolTypes,"NOSECOND"))
			{
				seconds=FALSE;
			}
			if(s=FindToolType(dobj->do_ToolTypes,"BACKTYPE"))
			{
				if(!strcmp(s,"COLOUR"))
				{
					backtype=BCOLOUR;
				}
				else if(!strcmp(s,"IMAGE"))
				{
					backtype=BIMAGE;
				}
				else if(!strcmp(s,"TRANSPARENT"))
				{
					backtype=BTRANSPARENT;
				}
			}
			if(s=FindToolType(dobj->do_ToolTypes,"OVAL"))
			{
				oval=TRUE;
			}
			if(s=FindToolType(dobj->do_ToolTypes,"SHOW"))
			{
				if(!strcmp(s,"NOTHING"))
				{
					showwhat=SWNOTHING;
				}
				else if(!strcmp(s,"TWELVE"))
				{
					showwhat=SWTWELVE;
				}
				else if(!strcmp(s,"QUARTERS"))
				{
					showwhat=SWQUARTERS;
				}
				else if(!strcmp(s,"HOURS"))
				{
					showwhat=SWHOURS;
				}
				else if(!strcmp(s,"MINUTES"))
				{
					showwhat=SWMINUTES;
				}
			}
			if(s=FindToolType(dobj->do_ToolTypes,"BACKFILE"))
			{
				strcpy(backimage,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"PUBSCREEN"))
			{
				strcpy(psname,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"QUARTERSOUND"))
			{
				strcpy(qsfn,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"HOURSOUND"))
			{
				strcpy(hsfn,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"ALARMSOUND"))
			{
				strcpy(asfn,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"ALARMCYCLES"))
			{
				alarmcycles=atoi(s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"FIXED"))
			{
				windowadjustable=FALSE;
			}
			if(s=FindToolType(dobj->do_ToolTypes,"SIZEASPICTURE"))
			{
				sizeaspicture=TRUE;
			}
			if(s=FindToolType(dobj->do_ToolTypes,"BORDERWIDTH"))
			{
				borderwidth=atoi(s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"BORDERHEIGHT"))
			{
				borderheight=atoi(s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"TOPEDGE"))
			{
				windowtopedge=atoi(s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"LEFTEDGE"))
			{
				windowleftedge=atoi(s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"WIDTH"))
			{
				windowwidth=atoi(s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"HEIGHT"))
			{
				windowheight=atoi(s);
			}

			if(s=FindToolType(dobj->do_ToolTypes,"BACKCOLOUR"))
			{
				setpen(&backcolour,s);
			}

			if(s=FindToolType(dobj->do_ToolTypes,"HOUR1"))
			{
				setpen(&hour1,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"HOUR2"))
			{
				setpen(&hour2,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"MINUTE1"))
			{
				setpen(&minute1,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"MINUTE2"))
			{
				setpen(&minute2,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"SECOND1"))
			{
				setpen(&second1,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"SECOND2"))
			{
				setpen(&second2,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"TWELVE1"))
			{
				setpen(&twelve1,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"TWELVE2"))
			{
				setpen(&twelve2,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"QUARTERS1"))
			{
				setpen(&quarters1,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"QUARTERS2"))
			{
				setpen(&quarters2,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"HOURS1"))
			{
				setpen(&hours1,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"HOURS2"))
			{
				setpen(&hours2,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"MINUTES1"))
			{
				setpen(&minutes1,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"MINUTES2"))
			{
				setpen(&minutes2,s);
			}

			if(s=FindToolType(dobj->do_ToolTypes,"HOURFIG"))
			{
				strcpy(hourf,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"MINUTEFIG"))
			{
				strcpy(minutef,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"SECONDFIG"))
			{
				strcpy(secondf,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"TWELVEFIG"))
			{
				strcpy(twelvef,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"QUARTERSFIG"))
			{
				strcpy(quartersf,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"HOURSFIG"))
			{
				strcpy(hoursf,s);
			}
			if(s=FindToolType(dobj->do_ToolTypes,"MINUTESFIG"))
			{
				strcpy(minutesf,s);
			}

			FreeDiskObject(dobj);
		}
		CurrentDir(oldcd);
		if(argc)
			UnLock(pdcd);
	}

	for(a=0;a<60;a++)
	{
		co2[a]=co[a]=256*cos(-2*PI*a/60);
   		si2[a]=si[a]=256*sin(-2*PI*a/60);
   		if(abs(si2[a])>abs(co2[a]))
   		{
   			co2[a]=(co2[a]*256)/abs(si2[a]);
   			si2[a]=256*sgn(si2[a]);
   		}
   		else
   		{
   			si2[a]=(si2[a]*256)/abs(co2[a]);
   			co2[a]=256*sgn(co2[a]);
   		}
	}
	
	tmp=CreateMsgPort();
	if(!tmp)
	{
		return(rc);
	}
	tior=CreateIORequest(tmp,sizeof(struct timerequest));
	if(!tior)
	{
		DeleteMsgPort(tmp);
		return(rc);
	}
	if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)tior,0))
	{
		DeleteIORequest((struct IORequest *)tior);
		DeleteMsgPort(tmp);
		return(rc);
	}
	
	tior->tr_time.tv_secs=1;
	tior->tr_time.tv_micro=0;
	tior->tr_node.io_Command=TR_ADDREQUEST;
	SendIO((struct IORequest *)tior);
	
	minute=readfig(minutef);
	hour=readfig(hourf);
	second=readfig(secondf);
	twelve=readfig(twelvef);
	quarters=readfig(quartersf);
	hours=readfig(hoursf);
	minutes=readfig(minutesf);

	/* For screennotify.library: */
	if((strcmp(psname,"Workbench")==0) && (ScreenNotifyBase=OpenLibrary(SCREENNOTIFY_NAME,SCREENNOTIFY_VERSION)))
	{
		if(snmp=CreateMsgPort())
		{
			if(!(snhandle=AddWorkbenchClient(snmp,0)))
			{
				DeleteMsgPort(snmp);
				CloseLibrary(ScreenNotifyBase);
				ScreenNotifyBase=NULL;
			}
		}
		else
		{
			CloseLibrary(ScreenNotifyBase);
			ScreenNotifyBase=NULL;
		}
	}

	while(noexit)
	{
		noexit=0;
		if(sc=LockPubScreen(psname))
		{
			if(vi=GetVisualInfo(sc,TAG_DONE))
			{
				if(menu=CreateMenus(scmenu,TAG_DONE))
				{
					if(LayoutMenus(menu,vi,GTMN_NewLookMenus,TRUE))
					{
						if(backtype==BIMAGE)
						{
							if(dto=NewDTObject ((APTR)backimage,DTA_GroupID,GID_PICTURE,PDTA_FreeSourceBitMap,TRUE,PDTA_Screen,sc,TRUE,TAG_DONE))
							{
		    				  	dtf.MethodID = DTM_FRAMEBOX;
			      				dtf.dtf_GInfo=NULL;
		      					dtf.dtf_FrameInfo = &fri;
		    	  				dtf.dtf_ContentsInfo = &fri;
	    	  					dtf.dtf_SizeFrameInfo = sizeof (struct FrameInfo);
    	    	    		    dtf.dtf_FrameFlags=0;
                	
    							if(DoDTMethodA(dto,NULL,NULL,(Msg)&dtf) && fri.fri_Dimensions.Depth)
	    						{
    								transw=fri.fri_Dimensions.Width;
	    							transh=fri.fri_Dimensions.Height;
	    							gpl.MethodID=DTM_PROCLAYOUT;
    								gpl.gpl_GInfo=NULL;
    								gpl.gpl_Initial=1L;
	    					
							        DoDTMethodA (dto, NULL, NULL, (Msg)&gpl);
				
							        	GetDTAttrs (dto, PDTA_DestBitMap, &trans, PDTA_BitMapHeader, &bmh, TAG_END);
							        if(bmh)
							        {
				    			    	transw=bmh->bmh_Width;
    									transh=bmh->bmh_Height;
						    	    }
									if(!trans)
									{
										DisposeDTObject(dto);
										dto=NULL;
										backtype=BCOLOUR;						
									}
									if(backtype==BIMAGE && sizeaspicture)
									{
										windowwidth=transw;
										windowheight=transh;
									}
			    				}
								else
								{
									DisposeDTObject(dto);
									dto=NULL;
									backtype=BCOLOUR;
								}
							}
							else
							{
								backtype=BCOLOUR;
							}
						}
						if(chimestype!=CNONE)
						{
							if(hsfn[0])
								hso=NewDTObject ((APTR)hsfn,DTA_GroupID,GID_SOUND,TAG_DONE);
							if(qsfn[0])
								qso=NewDTObject ((APTR)qsfn,DTA_GroupID,GID_SOUND,TAG_DONE);
						}
						if(asfn[0])
							aso=NewDTObject ((APTR)asfn,DTA_GroupID,GID_SOUND,SDTA_Cycles,alarmcycles,TAG_DONE);
							
						if(di=GetScreenDrawInfo(sc))
						{		
							ULONG iclass;
							UWORD icode;
							APTR iaddr;
							struct MenuItem *item;
							ULONG what;
							
							if(wopen())
							{
								noexit=1;
	    	    	        	while(running)
	        	    		    {
									what=(1L<<(wi->UserPort->mp_SigBit) | (1L<<tmp->mp_SigBit));
									if(ScreenNotifyBase)
									{
										what|=(1L<<snmp->mp_SigBit);
									}
									if(awi)
									{
										what|=(1L<<awi->UserPort->mp_SigBit);
									}

	            		    		signals=Wait(what);
	            	    	
	            	    			if(ScreenNotifyBase && (signals & (1L<<snmp->mp_SigBit)))
	            	    			{
	            	    				if(snm=(struct ScreenNotifyMessage *)GetMsg(snmp))
	            	    				{
	            	    					if(snm->snm_Value)
	            	    					{
	            	    						ReplyMsg((struct Message *)snm);
	            	    					}
	            	    					else
	            	    					{
	            	    						running=FALSE;
	            	    					}
	            	    				}
	            	    			}
	            	    	
	            	    			if(signals & (1L<<(awi->UserPort->mp_SigBit)))
	            	    			{
	            	    				a=FALSE;
	            	    				while(awi && (im=(struct IntuiMessage *)GT_GetIMsg(awi->UserPort)))
	            	    				{
	            	    					iclass=im->Class;
		    	    	        			icode=im->Code;
		    	    	        			iaddr=im->IAddress;
		    	    	        			
		    	    	        			GT_ReplyIMsg(im);
		    	    	        			
		    	    	        			switch(iclass)
		    	    	        			{
		    	    	        				case IDCMP_GADGETUP:
		    	    	        					switch(((struct Gadget *)(iaddr))->GadgetID)
		    	    	        					{
		    	    	        						case ID_HOURS:
		    	    	        						case ID_MINUTES:
		    	    	        							a=TRUE;
		    	    	        							break;
		    	    	        						case ID_USE:
	    	    	        								GT_GetGadgetAttrs(slhoursgad,awi,NULL,GTSL_Level,&alarmhours,TAG_DONE);
															GT_GetGadgetAttrs(slminutesgad,awi,NULL,GTSL_Level,&alarmminutes,TAG_DONE);
		    	    	        						case ID_CANCEL:
		    	    	        							awiclose();
		    	    	        							break;
		    	    	        					}
		    	    	        					break;
		    	    	        				case IDCMP_REFRESHWINDOW:
			    	    	        				GT_RefreshWindow(awi,NULL);
		    	    	        					break;
		    	    	        			}
	            	    				}
	            	    				if(awi && a)
	            	    					updatetext();
	            	    			}
	            	    	
	        	        			if(signals & (1L<<(wi->UserPort->mp_SigBit)) )
			                		{
		    	        	    		while(im=(struct IntuiMessage *)GT_GetIMsg(wi->UserPort))
		    	    	        		{
		    	    	        			iclass=im->Class;
		    	    	        			icode=im->Code;
		    	    	        			
		    	    	        			GT_ReplyIMsg(im);
		    	    	        			
		    	    	        			
	    			            			switch(iclass)
		    	    	    	    		{
	            	    						case IDCMP_NEWSIZE:
													windowleftedge=wi->LeftEdge;
													windowtopedge=wi->TopEdge;
													windowwidth=wi->Width;
													windowheight=wi->Height;
		
			            							drawborder();
			            							initbufferbackgd();
			            							draw(TRUE);
						    						break;
	        		        					case IDCMP_REFRESHWINDOW:
						    	    	            drawborder();
							    	                draw(TRUE);
	        	        							break;
	    	            						case IDCMP_VANILLAKEY:
		            	    						if(icode==27)
		            	    						{
	            	    								running=noexit=0;
	        	        							}
				                					break;
		    		            				case IDCMP_ACTIVEWINDOW:
	        		        						drawborder();
	            		    						break;
	            			    				case IDCMP_INACTIVEWINDOW:
					    		    	            drawborder();
	    	            							break;
		                						case IDCMP_CHANGEWINDOW:
	                    							windowleftedge=wi->LeftEdge;
													windowtopedge=wi->TopEdge;
													windowwidth=wi->Width;
													windowheight=wi->Height;
			
	    	    	        		                transcounter=2;
	        		    		    				break;
	        		    		    			case IDCMP_MENUPICK:
	        		    		    				item=ItemAddress(menu,icode);
	        		    		    				switch((int)MENU_USERDATA(item))
	        		    		    				{
	        		    		    					case MENU_ABOUT:
	        		    		    						SetWindowPointer(wi,WA_BusyPointer,TRUE,TAG_DONE);
	        		    		    						EasyRequest(wi,&aboutes,NULL);
	        		    		    						SetWindowPointer(wi,WA_Pointer,NULL,TAG_DONE);
	        		    		    						break;
	        		    		    					case MENU_QUIT:
	        		    		    						running=noexit=0;
	        		    		    						break;
	        		    		    					case MENU_ALARMSWITCH:
	        		    		    						if(item->Flags && CHECKED)
	        		    		    						{
	        		    		    							alarmon=TRUE;
	        		    		    						}
	        		    		    						else
	        		    		    						{
	        		    		    							alarmon=FALSE;
	        		    		    						}
	        		    		    						break;
	        		    		    					case MENU_ALARMSET:
	        		    		    						awiopen();
	        		    		    						break;
	        		    		    				}
	        		    		    				break;
	        				        		}
				                		}
			    	            	}
		    	    	        	if(signals & (1L<<tmp->mp_SigBit))
	        	    	    		{
		        	    		    	if(CheckIO((struct IORequest *)tior))
		            		    		{
		            	    				struct DateStamp ds;
		        	        				int k;
			                	
				                			WaitIO((struct IORequest *)tior);
			    	            			if(transcounter)
					    	            	{
	    			    	        			if(!--transcounter)
	        			    	    			{
	            			    					running=1;
	            			    					if(backtype==BTRANSPARENT)
	            				    				{
	            			    						wclose();
		            	    							Delay(25);
		    		            						wopen();
	    			            					}
			        	        				}
		    	        	    				else
	        	        						{
	            	    							draw(FALSE);
	                							}
			            	    			}
				            		    	else
				        	        		{
				    	            			draw(FALSE);
					    	            	}
				        	        	
					            	    	ds.ds_Days=ds.ds_Minute=ds.ds_Tick=0;
				    	            		DateStamp(&ds);
				        	        		k=(50-ds.ds_Tick%50)*20000;
			                	
				        	        		tior->tr_time.tv_secs=0;
											tior->tr_time.tv_micro=k;
											tior->tr_node.io_Command=TR_ADDREQUEST;
											SendIO((struct IORequest *)tior);
			            		    	}
			        	        	}
		    		            }
								rc=0;
								
								if(awi)
								{
									awiclose();
								}
								
								wclose();
					
								if(trans && backtype!=BIMAGE)
								{
									FreeBitMap(trans);
								}
							}
							FreeScreenDrawInfo(sc,di);
						}
						if(dto)
						{
							DisposeDTObject(dto);
						}
				
						if(aso)
						{
							DisposeDTObject(aso);
						}
						if(hso)
						{
							DisposeDTObject(hso);
						}
						if(qso)
						{
							DisposeDTObject(qso);
						}
					}
					FreeMenus(menu);
				}
				FreeVisualInfo(vi);
			}
			UnlockPubScreen(NULL,sc);
		}
		if(ScreenNotifyBase && noexit)
		{
			ReplyMsg((struct Message *)snm);
			while(!running)
			{
				WaitPort(snmp);
				if(snm=(struct ScreenNotifyMessage *)GetMsg(snmp))
				{
					if(snm->snm_Value)
					{
						running=TRUE;
					}
					ReplyMsg((struct Message *)snm);
				}
			}
		}
	}
	
	if(ScreenNotifyBase)
	{
		RemWorkbenchClient(snhandle);
		CloseLibrary(ScreenNotifyBase);
	}
	
    if(!CheckIO((struct IORequest *)tior))
    	AbortIO((struct IORequest *)tior);
    WaitIO((struct IORequest *)tior);
    
	CloseDevice((struct IORequest *)tior);
	DeleteIORequest((struct IORequest *)tior);
	DeleteMsgPort(tmp);

	if(minute)
	{
		free(minute);
	}
	if(hour)
	{
		free(hour);
	}
	if(second)
	{
		free(second);
	}
	if(twelve)
	{
		free(twelve);
	}
	if(hours)
	{
		free(hours);
	}
	if(quarters)
	{
		free(quarters);
	}
	if(minutes)
	{
		free(minutes);
	}
	
	if (LocaleBase)
	{
		if(catalog)
			CloseCatalog(catalog);
		CloseLibrary(LocaleBase);
	}

	return rc;
}

