
/*
 *  CLOCK.C	simple clock program
 */

#include <local/typedefs.h>

short Params[] = {
    'ST','RT', 0, 0,
    'NW','  ', 0, 8, -1, 10, 40, 20,
    'TE','XT', 0,16, 'HI','\0T','ES','T.', 0, 0, 0, 0,
    'EN','D ', 0, 0
};

#define WPOSX	8
#define WPOSY	9
#define WWIDTH	10
#define WHEIGHT 11

APTR IntuitionBase;
APTR GfxBase;

NW Nw = {
    0, 0, 0, 0, 0, 0,
    CLOSEWINDOW|REFRESHWINDOW|ACTIVEWINDOW|INACTIVEWINDOW,
    SIMPLE_REFRESH|WINDOWCLOSE|BACKDROP|RMBTRAP,
    NULL, NULL, (ubyte *)"", NULL, NULL, 4, 4, -1, -1, WBENCHSCREEN
};

short Sin[60+15] = {
      0,  27,  53,  79, 104, 128, 150, 171, 190, 207, 222, 234, 243, 250, 255,
    256, 255, 250, 243, 234, 222, 207, 190, 171, 150, 128, 104,  79,  53,  27,
      0, -27, -53, -79,-104,-128,-150,-171,-190,-207,-222,-234,-243,-250,-255,
   -256,-255,-250,-243,-234,-222,-207,-190,-171,-150,-128,-104, -79, -53, -27,
      0,  27,  53,  79, 104, 128, 150, 171, 190, 207, 222, 234, 243, 250, 255
};

#define Cos (Sin+15)

_main(ac, av)
char *av[];
{
    IOT  Iot;	    /*	timer request,	1 second internals  */
    SCR  Scr;
    WIN  *Win;
    PORT TPort;     /*	port for timer request		    */
    long TMask;
    long WMask;
    long error = 20;
    char notdone = 1;

    bzero(&Iot, sizeof(Iot));
    bzero(&TPort, sizeof(TPort));

    if (!(IntuitionBase = OpenLibrary("intuition.library", 0)))
	goto dieilib;
    if (!(GfxBase = OpenLibrary("graphics.library", 0)))
	goto dieglib;
    if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0))
	goto diedev;
    if (!GetScreenData(&Scr, sizeof(Scr), WBENCHSCREEN, NULL))
	goto diewin;

    Nw.Width  = Params[WWIDTH];
    Nw.Height = Params[WHEIGHT];
    Nw.LeftEdge = Params[WPOSX];
    Nw.TopEdge	= Params[WPOSY];
    if (Nw.Width <= 0)
	Nw.Width += Scr.Width;
    if (Nw.Height <= 0)
	Nw.Height += Scr.Height;
    if (Nw.LeftEdge < 0)
	Nw.LeftEdge += Scr.Width - Nw.Width;
    if (Nw.TopEdge < 0)
	Nw.TopEdge  += Scr.Height- Nw.Height;
    if (Nw.LeftEdge < 0 || Nw.TopEdge < 0 || Nw.LeftEdge + Nw.Width > Scr.Width || Nw.TopEdge + Nw.Height > Scr.Height) {
	Nw.LeftEdge = Nw.TopEdge = 0;
	Nw.Width = 64;
	Nw.Height= 32;
    }

    if (!(Win = OpenWindow(&Nw)))
	goto diewin;

    ShowTitle(Win->WScreen, 0);

    TPort.mp_Node.ln_Type = NT_MSGPORT;
    TPort.mp_SigTask = FindTask(NULL);
    TPort.mp_SigBit = AllocSignal(-1);
    TPort.mp_Flags  = PA_SIGNAL;
    NewList(&TPort.mp_MsgList);

    Iot.tr_node.io_Message.mn_ReplyPort = &TPort;
    Iot.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
    Iot.tr_node.io_Command = TR_ADDREQUEST;
    Iot.tr_time.tv_secs = 1;
    Iot.tr_time.tv_micro= 0;
    SendIO(&Iot);

    TMask = 1 << TPort.mp_SigBit;
    WMask = 1 << Win->UserPort->mp_SigBit;

    error = 0;
    while (notdone) {
	register long mask = Wait(TMask|WMask);
	if (mask & TMask) {
	    register short secs;
	    WaitIO(&Iot);
	    secs = UpdateWindow(Win);
	    Iot.tr_time.tv_secs = 65 - secs;
	    Iot.tr_time.tv_micro= 0;
	    Iot.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
	    SendIO(&Iot);
	}
	if (mask & WMask) {
	    register IMESS *im;
	    while (im = GetMsg(Win->UserPort)) {
		switch(im->Class) {
		case CLOSEWINDOW:
		    notdone = 0;
		    break;
		case REFRESHWINDOW:
		    BeginRefresh(Win);
		    EndRefresh(Win);
		case ACTIVEWINDOW:
		case INACTIVEWINDOW:
		    UpdateWindow(Win);
		    break;
		}
		ReplyMsg(im);
	    }
	}
    }
    AbortIO(&Iot);
    WaitIO(&Iot);
    FreeSignal(TPort.mp_SigBit);

    CloseWindow(Win);
diewin:
    CloseDevice(&Iot);
diedev:
    CloseLibrary(GfxBase);
dieglib:
    CloseLibrary(IntuitionBase);
dieilib:
    _exit(error);
}

/*
 *  Update the window
 *
 *  (1) RectFill
 *  (2) minute and hour hands
 */

UpdateWindow(win)
register WIN *win;
{
    register RP *rp = win->RPort;
    DATESTAMP DS;
    short minutes;
    short hours;
    short radiusx, radiusy;
    short centerx, centery;

    DateStamp(&DS);
    minutes = DS.ds_Minute % 60;
    hours   = (DS.ds_Minute / 12) % 60;     /*  0 to 59 (partial hours indicator)   */
    radiusx = (win->Width - 2) >> 1;
    radiusy = (win->Height- 2) >> 1;
    centerx = 1 + radiusx;
    centery = 1 + radiusy;
    SetAPen(rp, 0);
    RectFill(rp, 0, 0, win->Width - 1, win->Height - 1);
    SetAPen(rp, 1);
    {
	register short i;
	for (i = 0; i < 60; i += 5) {
	    Move(rp, centerx + ((radiusx * Sin[i]) >> 8), centery + ((radiusy * -Cos[i]) >> 8));
	    Draw(rp, centerx + ((radiusx * Sin[i]) >> 8), centery + ((radiusy * -Cos[i]) >> 8));
	}
    }
    radiusx -= 2;
    radiusy -= 2;

    SetAPen(rp, 3);                 /*  minutes */
    Move(rp, centerx, centery);
    Draw(rp, centerx + ((radiusx * Sin[minutes]) >> 8), centery + ((radiusy * -Cos[minutes]) >> 8));
    SetAPen(rp, 2);                 /*  hours   */
    Move(rp, centerx, centery);
    Draw(rp, centerx + ((radiusx * Sin[hours]) / 384), centery + ((radiusy * -Cos[hours]) / 384));
    return(DS.ds_Tick / 50 % 60);  /*  seconds */
}

#asm

	    ; bzero(buf, bytes)
	    ;	    4sp   8sp
	    ;
	    ;	SIMPLE STUPID BZERO .. I don't even use DBF (don't want to
	    ;				have to think at this time of night)

_bzero:
	    moveq.l #0,D1
	    move.l  4(sp),A0
	    move.l  8(sp),D0
	    beq     bze
bz1	    move.b  D1,(A0)+
	    subq.l  #1,D0
	    bne     bz1
bze	    rts


#endasm

