/* DClock.c *****************************************************************
*
*	DClock --------	A  Dumb  Clock  Utility,  my  idea  of how a clock
*			should really be like.
*
*			Since  I  own my Amiga I have known almost as many
*			clock  utilities  as  there  are  bugs  in the ROM
*			Operating  System  (sorry,  this was supposed to a
*			joke).   None  really  satisfied  my  needs,  even
*			though  a  lot of them had shelfloads of features.
*			Their  windows always blocked the scrolling inside
*			of  CLI  windows   which  didn't look very pretty.
*			Sometimes  they  occupied a lot of memory, such as
*			MachII.   Then  I  stumbled  upon  a MacIntosh and
*			DMouse.   At  the  left  hand of a Mac display you
*			will  find  a  small  clock  display.  Well, isn't
*			there  a  Workbench  we  could  use to display our
*			clock?   From  DMouse  I  borrowed  the very basic
*			program  structure  (I  hope you don't mind Matt).
*			To            avoid            the            slow
*			Window/SMART_REFRESH/ScrollRaster()   interaction,
*			the  clock  uses  the  barlayer  of  the Workbench
*			screen.
*			Once   trying   to  improve  the  handler  I  also
*			incorporated   my   DisplayBeep.c  code  into  it.
*			DisplayBeep  'beeps' both audible and visible, the
*			old Intuition routine only flashed the display.  I
*			also added the contents of my Click.c program.
*
*	Author --------	Olaf 'Olsen' Barthel, ED Electronic Design Hannover
*			Brabeckstrasse 35
*			D-3000 Hannover 71
*
*			Federal Republic of Germany
*
*	This  program  truly is in the PUBLIC DOMAIN.  Written on a cold
*	and  damp  September  evening,  hoping the next morning would be
*	better.
*
*	Compiled using Aztec C 3.6a, CygnusEd Professional & ARexx.
*
****************************************************************************/

	/* These belong to ARP. */

#include <libraries/arpbase.h>
#include <arpfunctions.h>

#include "DClock.h"

	/* ARP help messages. */

char *CLI_Template	= "QUIT/S,INFO/S,BEEP/K,CLICK/K,CLICKVOLUME/K,PRIORITY/K,TEXTCOLOUR/K,BACKCOLOUR/K,ALARM/K,ALARMTIME/K";
char *CLI_Help		= "\nUsage: DClock [QUIT] [INFO] [BEEP ON|OFF] [CLICK ON|OFF] [CLICKVOLUME 0-64]\
\n              [PRIORITY 0 - 127] [TEXTCOLOUR #] [BACKCOLOUR #]\n              [ALARM ON|OFF|INFO] [ALARMTIME HH:MM:SS]\n";

	/* Where to find the different arguments. */

#define ARG_QUIT	1
#define ARG_INFO	2
#define ARG_BEEP	3
#define ARG_CLICK	4
#define ARG_CLICKVOLUME	5
#define ARG_PRIORITY	6
#define ARG_TEXTCOLOUR	7
#define ARG_BACKCOLOUR	8
#define ARG_ALARM	9
#define ARG_ALARMTIME	10

	/* Stub, don't need these. */

void _wb_parse() {}
long Chk_Abort() { return(0); }

	/* main(argc,argv):
	 *
	 *	That's where all the trouble starts.
	 */

void
main(argc,argv)
long argc;
char *argv[];
{
		/* Are we already running? */

	register struct DSeg *DSeg = (struct DSeg *)FindPort(PORTNAME);

		/* No argument and DClock's already running? */

	if(argc < 2 && DSeg)
	{
		Printf("Can't install DClock, handler process already running\7!\n");

		exit(0);
	}

		/* User wants information. */

	if(argv[ARG_INFO])
	{
		Printf("\n\33[1m\33[33mDClock\33[0m\33[31m - A \33[33mD\33[31mumb \33[33mClock\33[31m. Renders time and date\n");
		Printf("         into the Workbench title bar. Place\n");
		Printf("         \33[33mDClock-Handler\33[31m in L:, \33[33mDClock\33[31m somewhere\n");
		Printf("         in C: or in SYS:. Type '\33[1m\33[33mDClock\33[31m\33[0m' to\n");
		Printf("         install, '\33[1m\33[33mDClock quit\33[31m\33[0m' to remove.\n\n");
		Printf("         \33[33mDClock\33[31m is \33[1mfree\33[0m and in the \33[33m\33[1mPUBLIC-DOMAIN\33[31m\33[0m!\n\n");

		Printf("\33[1m\33[33mAuthor\33[31m\33[0m - Olaf Barthel of ED Electronic Design Hannover\n");
		Printf("         Brabeckstrasse 35\n");
		Printf("         D-3000 Hannover 71\n\n");

		Printf("	 Federal Republic of Germany.\n\n");

		exit(0);
	}

		/* Terminate dumb clock? */

	if(argv[ARG_QUIT])
	{
		Printf("Removing \33[1m\33[33mDClock\33[31m\33[0m, ");

			/* Segment not loaded. */

		if(!DSeg)
		{
			Printf("failed!\7\n");
			exit(0);
		}

			/* We are the caller. */

		DSeg -> Father = (struct Task *)FindTask(NULL);

			/* Child still present? */

		if(DSeg -> Child)
		{
			Signal(DSeg -> Child,SIGBREAKF_CTRL_D);
			Wait(SIGBREAKF_CTRL_D);
		}

			/* Remove port and associated data. */

		RemPort(&DSeg -> Port);
		FreeMem(DSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));

		if(DSeg -> Segment)
			UnLoadPrg(DSeg -> Segment);

		FreeMem(DSeg,DSeg -> SegSize);

		Printf("OK.\n");

		exit(0);
	}

		/* Create global communication structure. */

	if(!DSeg)
	{
		if(DSeg = (struct DSeg *)AllocMem(sizeof(struct DSeg),MEMF_PUBLIC | MEMF_CLEAR))
		{
			ULONG Micros;

				/* Dummy MessagePort. */

			DSeg -> Port . mp_Flags		= PA_IGNORE;
			DSeg -> Port . mp_Node . ln_Pri	= 0;
			DSeg -> Port . mp_Node . ln_Type= NT_MSGPORT;
			DSeg -> Port . mp_Node . ln_Name= AllocMem(sizeof(PORTNAME),MEMF_PUBLIC);
			DSeg -> Child			= NULL;

				/* For future expansion of this structure,
				 * this will insure that any version of
				 * DClock will be able to free the memory
				 * occupied by the segment.
				 */

			DSeg -> SegSize			= sizeof(struct DSeg);

				/* Activate beep and click feature. */

			DSeg -> Beep			= TRUE;
			DSeg -> Click			= TRUE;

				/* So we have valid time counter. */

			CurrentTime(&DSeg -> LastSecs,&Micros);

				/* Click volume and handler priority. */

			DSeg -> ClickVolume		= 64;
			DSeg -> Priority		= 5;

				/* Rendering colours. */

			DSeg -> TextColour		= 0;
			DSeg -> BackColour		= 1;

			DSeg -> Alarm			= FALSE;

			DSeg -> AlarmHour		= 12;
			DSeg -> AlarmMinute		= 0;
			DSeg -> AlarmSecond		= 0;

				/* Install the current revision number. */

			DSeg -> Revision		= REVISION;

				/* Changed handler priority. */

			if(argv[ARG_PRIORITY])
				Printf("DClock: Handler priority set to %ld.\n",DSeg -> Priority = Atol(argv[ARG_PRIORITY]));

				/* Init port. */

			strcpy(DSeg -> Port . mp_Node . ln_Name,PORTNAME);

			NewList(&DSeg -> Port . mp_MsgList);

			Printf("Installing \33[33m\33[1mDClock\33[0m\33[31m, ");

				/* Load the handler code. */

			DSeg -> Segment = LoadPrg("DClock-Handler");

			if(!DSeg -> Segment)
				DSeg -> Segment = LoadPrg("L:DClock-Handler");

			if(!DSeg -> Segment)
			{
				Printf("unable to find \33[33mL:DClock-Handler\33[31m\7!\n");

				FreeMem(DSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
			}
			else
			{
					/* Install the port and start the handler. */

				AddPort(&DSeg -> Port);

				CreateProc("DClock-Handler",DSeg -> Priority,DSeg -> Segment,4096);

				Printf("OK. \33[33mDClock v1.%ld\33[31m, by ED Hannover. \33[1mPUBLIC DOMAIN\33[0m.\n",REVISION);
			}
		}
	}

		/* Change click volume. */

	if(argv[ARG_CLICKVOLUME] && DSeg)
	{
		if(Atol(argv[ARG_CLICKVOLUME]) > 0)
			Printf("DClock: Click volume set to %ld.\n",DSeg -> ClickVolume = Atol(argv[ARG_CLICKVOLUME]));
		else
			Puts(CLI_Help);
	}

		/* Change handler priority? */

	if(argv[ARG_PRIORITY] && DSeg)
	{
		if(DSeg -> Child)
		{
			Printf("DClock: Handler priority set to %ld.\n",DSeg -> Priority = Atol(argv[ARG_PRIORITY]));

			SetTaskPri(DSeg -> Child,DSeg -> Priority);
		}
		else
			Puts("DClock: Unable to find handler task.");
	}

		/* Turn beeping on/off? */

	if(argv[ARG_BEEP] && DSeg)
	{
		if(!Strcmp(argv[ARG_BEEP],"OFF"))
		{
			Puts("DClock: Beep disabled.");

			DSeg -> Beep = FALSE;
		}
		else
		{
			if(!Strcmp(argv[ARG_BEEP],"ON"))
			{
				Puts("DClock: Beep enabled.");

				DSeg -> Beep = TRUE;
			}
			else
				Puts(CLI_Help);
		}
	}

		/* Turn clicking on/off? */

	if(argv[ARG_CLICK])
	{
		if(!Strcmp(argv[ARG_CLICK],"OFF"))
		{
			Puts("DClock: Click disabled.");

			DSeg -> Click = FALSE;
		}
		else
		{
			if(!Strcmp(argv[ARG_CLICK],"ON"))
			{
				Puts("DClock: Click enabled.");

				DSeg -> Click = TRUE;
			}
			else
				Puts(CLI_Help);
		}
	}

		/* Select new front colour? */

	if(argv[ARG_TEXTCOLOUR])
	{
		DSeg -> TextColour = Atol(argv[ARG_TEXTCOLOUR]);

		Printf("DClock: Text colour set to %ld.\n",DSeg -> TextColour);
	}

		/* Select new background colour? */

	if(argv[ARG_BACKCOLOUR])
	{
		DSeg -> BackColour = Atol(argv[ARG_BACKCOLOUR]);

		Printf("DClock: Background colour set to %ld.\n",DSeg -> BackColour);
	}

		/* Set/check alarm status. */

	if(argv[ARG_ALARM])
	{
		if(!Strcmp(argv[ARG_ALARM],"OFF"))
		{
			Puts("DClock: Alarm disabled.");

			DSeg -> Alarm = FALSE;
		}
		else
		{
			if(!Strcmp(argv[ARG_ALARM],"ON"))
			{
				Puts("DClock: Alarm enabled.");

				DSeg -> Alarm = TRUE;
			}
			else
			{
				if(!Strcmp(argv[ARG_ALARM],"INFO"))
					Printf("DClock: Current alarm time is %02ld:%02ld:%02ld.\n",DSeg -> AlarmHour,DSeg -> AlarmMinute,DSeg -> AlarmSecond);
				else
					Puts(CLI_Help);
			}
		}
	}

		/* Adjust alarm time. */

	if(argv[ARG_ALARMTIME])
	{
		char TimeBuff[3];
		register long i,TheTime;

		TimeBuff[2] = 0;

		if(strlen(argv[ARG_ALARMTIME]) != 8)
		{
			Puts("DClock: Alarm time format = HH:MM:SS, example: 09:03:07.");
			exit(10);
		}

		TimeBuff[0] = argv[ARG_ALARMTIME][0];
		TimeBuff[1] = argv[ARG_ALARMTIME][1];

		TheTime = Atol(TimeBuff);

		if(TheTime < 0 || TheTime > 23)
		{
			Puts("DClock: Illegal time value, Hours must be within 0 ... 23.");
			exit(10);
		}

		DSeg -> AlarmHour	= TheTime;

		TimeBuff[0] = argv[ARG_ALARMTIME][3];
		TimeBuff[1] = argv[ARG_ALARMTIME][4];

		TheTime = Atol(TimeBuff);

		if(TheTime < 0 || TheTime > 59)
		{
			Puts("DClock: Illegal time value, Minutes must be within 0 ... 59.");
			exit(10);
		}

		DSeg -> AlarmMinute	= TheTime;

		TimeBuff[0] = argv[ARG_ALARMTIME][6];
		TimeBuff[1] = argv[ARG_ALARMTIME][7];

		TheTime = Atol(TimeBuff);

		if(TheTime < 0 || TheTime > 59)
		{
			Puts("DClock: Illegal time value, Seconds must be within 0 ... 59.");
			exit(10);
		}

		DSeg -> AlarmSecond	= TheTime;

		Printf("DClock: Alarm time set to %02ld:%02ld:%02ld.\n",DSeg -> AlarmHour,DSeg -> AlarmMinute,DSeg -> AlarmSecond);
	}
}
