/*
 * clock - a dumb, digital clock in the upper right-hand corner. Designed
 *	to be small, not flexible!
 *
 * Copyright (c) 1986, Mike Meyer
 *
 * Permission is hereby granted to distribute this program for any purposes
 * whatsoever, so long as this notice, including the above copyright, is
 * included with the distribution. Unlike other people, I don't care if you
 * make money off of this, so long as I get credit for having written it.
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <devices/timer.h>
#include <libraries/dos.h>
#include <intuition/intuition.h>

#include <stdio.h>

#define INTUITION_REV	1
/*
 * Things to tweak:
 *	WIN_WIDTH - the width of the window output screen. Should be 369.
 *	WAIT_TIME - how long to wait between updates. Also the maximum
 *		mis-time you can get.  Finally, it's the longest period of
 *		time you have to put up with the clock broken. Measured in
 *		micro-seconds.
 */
#define	WIN_WIDTH	369
#define WAIT_TIME	250000

static struct NewWindow	New_Window = {
	(590 - WIN_WIDTH), 0,	/* Upper right, out of the way */
	WIN_WIDTH, 10,		/* Just big enough for the time */
	-1, -1,			/* Default pens */
	CLOSEWINDOW,		/* All we care about is closing */
	WINDOWCLOSE		/* Borderless, fairly standard window */
	| WINDOWDEPTH | WINDOWDRAG | SMART_REFRESH | NOCAREREFRESH,
	(struct Gadget *) NULL,
	(struct Image *) NULL,
	"",			/* Empty title */
	(struct Screen *) NULL,
	(struct BitMap *) NULL,
	0, 0, 0, 0,		/* no change sizes, doesn't matter */
	WBENCHSCREEN		/* Of course! */
	} ;

static char	Date_Buffer[40] ;	/* Now you know where the time goes! */

static struct IntuiText	Date_Text = {
	1, 0,				/* Use the standard pen colors */
	JAM2,				/* Use both of them */
	0, 0,				/* in the upper left-hand corner */
	(struct TextAttr *) NULL,	/* Use default text */
	Date_Buffer,			/* Buffer for time */
	(struct IntuiText *) NULL	/* All of text */
	} ;

struct IntuitionBase	*IntuitionBase ;

/*
 * Some things that need to be shared with done.
 */
static struct Window		*Window = NULL ;
static struct timerequest	Time_Req ;
static struct MsgPort		*Timer_Port = NULL, *CreatePort() ;
#ifdef	DEBUG
static short			cli = FALSE ;
#endif

#ifdef	DEBUG
main(argc, argv) int argc; char *argv; {
#else
_main() {
#endif
	register short		hours, minutes ;
	register short		chip_free, fast_free ;
	struct DateStamp	now ;
	struct IntuiMessage	*Msg, *GetMsg() ;
	struct Task		*FindTask() ;
	ULONG			AvailMem() ;

#ifdef	DEBUG
	if (argc) cli = TRUE ;
#endif
	if ((IntuitionBase = (struct IntuitionBase *)
	    OpenLibrary("intuition.library", INTUITION_REV)) == NULL)
		done(20, "Can't open Intuition library") ;

	if ((Timer_Port = CreatePort("Timer Port", 0)) == NULL)
		done(20, "Can't create timer port") ;

	if (OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &Time_Req, 0) != NULL)
		done(20, "Can't open timer device") ;
	Time_Req . tr_node . io_Message . mn_ReplyPort = Timer_Port ;
	Time_Req . tr_node . io_Command = TR_ADDREQUEST ;
	Time_Req . tr_node . io_Flags = 0 ;
	Time_Req . tr_node . io_Error = 0 ;

	if ((Window = (struct Window *) OpenWindow(&New_Window)) == NULL)
		done(20, "Can't open window") ;
	
	/* Nudge me up to high priority */
	(void) SetTaskPri(FindTask((char *) 0), 20) ;

	for (;;) {
		DateStamp(&now) ;
		chip_free = AvailMem(MEMF_CHIP) >> 10;
		fast_free = AvailMem(MEMF_FAST) >> 10;
		hours = now . ds_Minute / 60 ;
		minutes = now . ds_Minute % 60 ;
		/* Oh, this hurts. But stdio, here we come.... */
		sprintf(Date_Buffer, " Chip:%3d  Fast:%4d  Time:%2d:%02d:%02d ",
					chip_free, fast_free, hours, minutes ,
					now . ds_Tick / TICKS_PER_SECOND) ;

		PrintIText(Window -> RPort, &Date_Text, 28, 1) ;

		Time_Req . tr_time . tv_secs = 0 ;
		Time_Req . tr_time . tv_micro = WAIT_TIME ;
		SendIO((char *) &Time_Req . tr_node) ;
		Wait(1 << Window -> UserPort -> mp_SigBit
		   | 1 << Timer_Port -> mp_SigBit) ;

		while (Msg = GetMsg(Window -> UserPort)) {
			if (Msg -> Class == CLOSEWINDOW) {
				ReplyMsg(Msg) ;
				done(0, "exit") ;
				}
			ReplyMsg(Msg) ;
			}

		(void) GetMsg(Timer_Port) ;
		}
	/* NOTREACHED */
	}
/*
 * done - just clean up that which is open, and then leave.
 */
done(how, why) int how; char *why; {

	AbortIO((char *) &Time_Req . tr_node) ;
	if (Window) CloseWindow(Window) ;
	if (Time_Req . tr_node . io_Message . mn_ReplyPort)
		CloseDevice(&Time_Req) ;
	if (Timer_Port) DeletePort(Timer_Port) ;
	if (IntuitionBase) CloseLibrary(IntuitionBase) ;
#ifdef	DEBUG
	if (cli) printf("clock: %s\n", why) ;
#endif

	OpenWorkBench() ;			/* As requested */
	exit(how) ;
	}
