#include <exec/types.h>
#include <intuition/intuition.h>
#include <devices/timer.h>
#include <workbench/startup.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <clib/intuition_protos.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <clib/wb_protos.h>
#include <clib/icon_protos.h>
#include <graphics/gfxbase.h>
#include <reqtools/reqtools.h>
#include <workbench/startup.h>
#include <workbench/workbench.h> 
#include <stdio.h> 
#include <string.h>

#include "Window.h"
#include "MenuDefs.h"
#include "Main.h"
#include "Draw.h"
#include "SetAlarm.h"


#define HANDLE_DONE 0
#define HANDLE_DRAGBAR 1
#define HANDLE_DATE 2
#define HANDLE_ICONIFY 3

// Prototypes ---------------------------------------------------------------

void wbmain(struct WBStartup *ws);
void main(int argc, char **argv);
int  HandleEvents(void);
BOOL OpenAllLibs(void);
void CloseAllLibs(void);
void About(void);
BOOL LoadPreferences(struct AppPrefs *prefs);
BOOL SavePreferences(struct AppPrefs *prefs);
BOOL OpenTimerDevice(void);
void CloseTimerDevice(void);
void SetTimer(ULONG delay);
int  Timeval2Seconds(int timeval);
int  Seconds2Timeval(int secs);
BOOL IsChecked(int menuNumber);
void DClockTask(void);
BOOL AllocateParentSignals(void);
void FreeParentSignals(void);
BOOL AllocateChildSignals(void);
void FreeChildSignals(void);
void InfoTask(void);
BOOL AllocateInfoSignals(void);
void FreeInfoSignals(void);
void SetCommand(int type);
int  myArgInt(char **argv, char *tool, int dfault);
char *myArgString(char **argv, char *tool, char *dfault);
BOOL myArgBool(char **argv, char *tool, BOOL dfault);
BOOL DoAppIcon(void);

// Statics ------------------------------------------------------------------

UBYTE *vers = "\0$VER: DClock V1.6 (c) 1995";
char PrefsName[] = "ENVARC:DClock.prefs";

struct IntuitionBase *IntuitionBase = NULL;
struct Library *GadToolsBase = NULL;
struct GfxBase *GfxBase = NULL;
struct ReqToolsBase *ReqToolsBase = NULL;
struct Library *IconBase = NULL;
struct Library *WorkbenchBase = NULL;

struct AppPrefs myPrefs =
{
	1,      // foreground color
	2,      // background color
	200,    // window position x
	10,     // window position y
	TRUE,   // display seconds: true/false
	FALSE,  // alarm on
	FALSE,  // timer on
	TRUE,   // dragbar
	0,      // alarmval
	0,      // timerval
	TRUE,   // twentyfour
	TRUE,   // date
	FALSE,  // activate
	TRUE    // date format dd-mm-yy
};

struct SignalSemaphore draw_semaphore = {0};
struct timerequest *TimerIO = NULL;
struct MsgPort *TimerMP = NULL;
struct Message *TimerMSG = NULL;
ULONG timerError = 1;

ULONG alarmsig, timersig, cleanupsig, exitsig, exit_info, info_done, alarmcmd, timercmd;
LONG alarmsignum, timersignum, cleanupsignum, exitsignum, exit_info_num, info_done_num, alarmcmdnum, timercmdnum;

struct Task *childtask;
struct Task *parenttask;
struct Task *infotask;

FILE *conwin = NULL; 
char *PubScreenName = NULL;

struct TagItem ezRequestTags[] =
{  RT_PubScrName, (ULONG)PubScreenName,
	TAG_DONE, 0
};
 
char DiskObjectName[256] = {0};  // Name of .info file

// Main function ------------------------------------------------------------

void wbmain(struct WBStartup *ws)
{
	struct DiskObject *dobj;
	int i = 0, argc = 1;
	struct WBArg *wbarg;
	LONG olddir = -1;
	char args[14][40];
	char *argv[14];
	char **toolarray;


	if (conwin = fopen("CON:10/10/540/200/Output/auto/close", "r+"))
	{
		if (IconBase = OpenLibrary("icon.library", 36L))
		{
			wbarg = ws->sm_ArgList;

			olddir = -1;
			if ((wbarg->wa_Lock) && (*wbarg->wa_Name))
				olddir = CurrentDir(wbarg->wa_Lock);

			strcpy(args[0], wbarg->wa_Name);
			dobj=(struct DiskObject *)GetDiskObject((UBYTE *)wbarg->wa_Name);

			if((*wbarg->wa_Name) && (dobj))
			{
				NameFromLock(wbarg->wa_Lock, DiskObjectName, 255);
				if (DiskObjectName[strlen(DiskObjectName) - 1] != ':')
					strcat(DiskObjectName, "/");
				strcat(DiskObjectName, wbarg->wa_Name);
				toolarray = dobj->do_ToolTypes;

				while(toolarray[i])
				{
					strcpy(args[i + 1], toolarray[i]);
					i++; argc++;
				}

				/* Free the diskobject we got */
				FreeDiskObject(dobj);
			}

			for (i = 0; i < argc; i++)
				argv[i] = (char *)&args[i];

			if (olddir != -1)
				CurrentDir(olddir);

			CloseLibrary(IconBase);
			IconBase = NULL;
		}
		else
			fprintf(conwin, "ERROR: Can't open icon.library V36+\n");

		main(argc, argv);
		fclose(conwin);
	}
}
 

void main(int argc, char **argv)
{
  int loop;
  struct Window *oldwinptr;

  if (DiskObjectName[0] == NULL)
	  strcpy(DiskObjectName, argv[0]);
	  // strcpy(DiskObjectName, "PROGDIR:DClock");

  if (OpenAllLibs())
  {
	  PubScreenName = myArgString(argv, "PUBSCREEN", "Workbench"); 
	  if (! LoadPreferences(&myPrefs))
	  {
		  rtEZRequestA("       DClock V1.6\n"
							"       ~~~~~~~~~~~\n"
							"Couldn't load preferences.\n"
							"The default values will be\n"
							"       used instead.\n",
							"Okay", NULL, NULL, ezRequestTags);
	  }
	  do
	  {
		  loop = HANDLE_DONE; 
		  if (! SetupScreen())
		  {
			  ezRequestTags[0].ti_Data = (ULONG)PubScreenName;

			  if (AllocateParentSignals())
			  {
				  if (! OpenDClockWindow(&myPrefs))
				  {
					  InitSemaphore(&draw_semaphore);
					  DrawTime(DClockWnd, &myPrefs);
					  parenttask = FindTask(NULL);
					  childtask = CreateTask("DClockTask", 0, (APTR)DClockTask, 4000L);
					  infotask = CreateTask("DClockInfo", 0, (APTR)InfoTask, 4000L);
					  Delay(30);
					  loop = HandleEvents();
					  Signal(childtask, exitsig);
					  Signal(infotask, exit_info);
					  Wait(cleanupsig);
					  Wait(info_done);
					  Forbid();
					  DeleteTask(childtask);
					  DeleteTask(infotask);
					  Permit();
					  myPrefs.windowX = DClockWnd->LeftEdge; // Save current
					  myPrefs.windowY = DClockWnd->TopEdge;  // window position
					  CloseDClockWindow();
				  }
			  }
			  FreeParentSignals(); /* This is safe */
			  CloseDownScreen();   /* Unlock screen to allow screenmode changes */

			  if (loop == HANDLE_ICONIFY)
			  {
				  if (! DoAppIcon())
					  rtEZRequestA("Sorry, cannot install AppIcon.",
										"Hmmm", NULL, NULL, ezRequestTags);


			  }
		  }
	  }
	  while (loop != HANDLE_DONE);
  }
  CloseAllLibs();  // This is safe. Function will check for valid pointers
}

// --------------------------------------------------------------------------

int HandleEvents(void)
{
	struct Window *actWindow = DClockWnd;
	struct Menu *actMenus = DClockMenus;
	struct IntuiMessage *msg;
	struct MenuItem *item, *it;
	BOOL done = FALSE;
	BOOL loop = FALSE;
	UWORD menuNumber;
	UWORD stripNum;
	UWORD itemNum;
	UWORD subNum;
	ULONG Class;
	UWORD Code;
	ULONG signal;
	ULONG windowSig = 1L << actWindow->UserPort->mp_SigBit;
	int timeval;
	int ret = HANDLE_DONE;

	while (! done)
	{
		signal = Wait(windowSig | cleanupsig | timercmd | alarmcmd);
		if (! (signal & windowSig))
			loop = FALSE;
		else
			loop = TRUE;

		if (signal & cleanupsig)
		{
			done = TRUE;
			loop = FALSE;
			 rtEZRequestA("Error:\n\n"
							  "Child task ended on error condition.\n"
							  "Either the timer device  couldn't be\n"
							  "opened or a signal allocation failed",
							  "Quit", NULL, NULL, ezRequestTags);
		}

		if (signal & timercmd)
		{
			char concmd[256];
			BPTR out;
			struct TagItem items[3];
 
			strcpy(concmd, "CON:0/0/640/200/DClock Output/AUTO/CLOSE/WAIT/SCREEN ");
			strcat(concmd, PubScreenName);
			out = Open(concmd, MODE_NEWFILE);

			items[0].ti_Tag = SYS_Input;  items[0].ti_Data = (ULONG)out;
			items[1].ti_Tag = SYS_Output; items[1].ti_Data = 0;
			items[2].ti_Tag = TAG_DONE;   items[2].ti_Data = 0;

			if (SystemTagList(myPrefs.timrcmd, items))
				rtEZRequestA("Oops, an  error occurred.\n"
								 "Check your timer command.",
								 "I'll do that", NULL, NULL, ezRequestTags);
			if (out)
				Close(out);
		}
		if (signal & alarmcmd)
		{
			char concmd[256];
			BPTR out;
			struct TagItem items[3];
 
			strcpy(concmd, "CON:0/0/640/200/DClock Output/AUTO/CLOSE/WAIT/SCREEN ");
			strcat(concmd, PubScreenName);
			out = Open(concmd, MODE_NEWFILE);

			items[0].ti_Tag = SYS_Input;  items[0].ti_Data = (ULONG)out;
			items[1].ti_Tag = SYS_Output; items[1].ti_Data = 0;
			items[2].ti_Tag = TAG_DONE;   items[2].ti_Data = 0;

			if (SystemTagList(myPrefs.alrmcmd, items))
				rtEZRequestA("Oops, an  error occurred.\n"
								 "Check your alarm command.",
								 "I'll do that", NULL, NULL, ezRequestTags);
			if (out)
				Close(out);
		}

		while ((! done) && (loop) && (msg = GT_GetIMsg(actWindow->UserPort)))
		{
			Class = msg->Class;
			Code = msg->Code;
			GT_ReplyIMsg(msg);
			switch (Class)
			{
				case IDCMP_REFRESHWINDOW:
					  DrawTime(DClockWnd, &myPrefs);
					  break;
				case IDCMP_MENUPICK:
					  menuNumber = Code;
					  while ((menuNumber != MENUNULL) && (! done))
					  {
						  item = ItemAddress(actMenus, menuNumber);

						  stripNum = MENUNUM(menuNumber);
						  itemNum = ITEMNUM(menuNumber);
						  subNum = SUBNUM(menuNumber);
						  switch (stripNum)
						  {
							  case MENU_DCLOCK:
								  switch (itemNum)
								  {
									  case MENU_SECONDS:
										  if (IsChecked(menuNumber))
											  myPrefs.seconds = TRUE;
										  else
											  myPrefs.seconds = FALSE;
										  DrawTime(DClockWnd, &myPrefs);
										  break;
									  case MENU_24H:
										  if (IsChecked(menuNumber))
											  myPrefs.twentyfour = TRUE;
										  else
											  myPrefs.twentyfour = FALSE;
										  DrawTime(DClockWnd, &myPrefs);
										  break;
									  case MENU_DATE:
										  if (IsChecked(menuNumber))
											  myPrefs.date = TRUE;
										  else
											  myPrefs.date = FALSE;
										  ret = HANDLE_DATE;
										  done = TRUE;
										  loop = FALSE;
										  break;
									  case MENU_DDMMYY:
										  if (IsChecked(menuNumber))
											  myPrefs.ddmmyy = TRUE;
										  else
											  myPrefs.ddmmyy = FALSE;
										  DrawTime(DClockWnd, &myPrefs);
										  break;
									  case MENU_ALARMON:
										  if (IsChecked(menuNumber))
										  {
											  myPrefs.alarm = TRUE;
											  DrawAlarm(myPrefs.foreground);
										  }
										  else
										  {
											  myPrefs.alarm = FALSE;
											  EraseAlarm(myPrefs.background);
										  }
										  break;
									  case MENU_TIMERON:
										  if (IsChecked(menuNumber))
										  {
											  myPrefs.timer = TRUE;
											  DrawTimer(myPrefs.foreground);
										  }
										  else
										  {
											  myPrefs.timer = FALSE;
											  EraseTimer(myPrefs.background);
										  }
										  break;
									  case MENU_SETALARM:
										  timeval = SetAlarm(SET_ALARM, myPrefs.alarmval);
										  if (timeval != SET_CANCEL)
										  {
											  myPrefs.alarmval = timeval;
											  it = (struct MenuItem *)ItemAddress(DClockMenus, FULLMENUNUM(MENU_DCLOCK, MENU_ALARMON, 0));
											  ClearMenuStrip(DClockWnd);
											  it->Flags = it->Flags | (CHECKED);
											  SetMenuStrip(DClockWnd, DClockMenus);
											  myPrefs.alarm = TRUE;
											  DrawAlarm(myPrefs.foreground);
										  }
										  break;
									  case MENU_SETTIMER:
										  timeval = SetAlarm(SET_TIMER, Seconds2Timeval(myPrefs.timerval));
										  if (timeval != SET_CANCEL)
										  {
											  myPrefs.timerval = Timeval2Seconds(timeval);
											  if (myPrefs.timerval > 0)
											  {
												  it = (struct MenuItem *)ItemAddress(DClockMenus, FULLMENUNUM(MENU_DCLOCK, MENU_TIMERON, 0));
												  ClearMenuStrip(DClockWnd);
												  it->Flags = it->Flags | (CHECKED);
												  SetMenuStrip(DClockWnd, DClockMenus);
												  OnMenu(DClockWnd, FULLMENUNUM(MENU_DCLOCK, MENU_TIMERON, 0));
												  myPrefs.timer = TRUE;
												  DrawTimer(myPrefs.foreground);
											  }
											  else
												  TurnTimerOff(&myPrefs);
										  }
										  break;
									  case MENU_ALARMCMD:
										  SetCommand(ALARM);
										  break;
									  case MENU_TIMERCMD:
										  SetCommand(TIMER);
										  break;
									  case MENU_SAVEPREFS:
										  if (! SavePreferences(&myPrefs))
										  {
											  rtEZRequestA("          DClock V1.6\n"
																"          ~~~~~~~~~~~\n"
																"Couldn't save preferences to ENVARC:\n",
																"Okay", NULL, NULL, ezRequestTags);
										  }
										  break;
									  case MENU_ABOUT:
										  About();
										  break;
									  case MENU_QUIT:
										  ret = HANDLE_DONE;
										  done = TRUE;
										  loop = FALSE;
										  break;
								  }
								  break;
							  case MENU_WINDOW:
								  switch (itemNum)
								  {
									  case MENU_FOREGROUND:
										  myPrefs.foreground = subNum;
										  DrawTime(DClockWnd, &myPrefs);
										  break;
									  case MENU_BACKGROUND:
										  myPrefs.background = subNum;
										  DrawTime(DClockWnd, &myPrefs);
										  break;
									  case MENU_DRAGBAR:
										  if (IsChecked(menuNumber))
											  myPrefs.dragbar = TRUE;
										  else
											  myPrefs.dragbar = FALSE;
										  ret = HANDLE_DRAGBAR;
										  done = TRUE;
										  loop = FALSE;
										  break;
									  case MENU_ACTIVATE:
										  if (IsChecked(menuNumber))
											  myPrefs.activate = TRUE;
										  else
											  myPrefs.activate = FALSE;
										  break;
									  case MENU_ICONIFY:
										  ret = HANDLE_ICONIFY;
										  done = TRUE;
										  loop = FALSE;
										  break;
								  }
								  break;
						  }
						  menuNumber = item->NextSelect;
					  }
			}
		}
	}
	while (msg = GT_GetIMsg(actWindow->UserPort)) ;
	return ret;
}

// --------------------------------------------------------------------------

BOOL OpenAllLibs(void)
{
	ReqToolsBase = (struct ReqToolsBase *)OpenLibrary(REQTOOLSNAME,REQTOOLSVERSION);
	if (ReqToolsBase)
	{
		IntuitionBase = (struct IntuitionBase *)ReqToolsBase->IntuitionBase;
		GadToolsBase = (struct Library *)ReqToolsBase->GadToolsBase;
		GfxBase = (struct GfxBase *)ReqToolsBase->GfxBase;
	}
	IconBase = OpenLibrary("icon.library", 36L);
	WorkbenchBase = OpenLibrary("workbench.library", 37L);

	return (ReqToolsBase && IconBase && WorkbenchBase);
}

void CloseAllLibs(void)
{
	if (ReqToolsBase)
		CloseLibrary((struct Library *)ReqToolsBase);
	if (IconBase)
		CloseLibrary(IconBase);
	if (WorkbenchBase)
		CloseLibrary(WorkbenchBase);
}

// --------------------------------------------------------------------------

void About(void)
{
	rtEZRequestA("        DClock V1.6\n"
					 "        ~~~~~~~~~~~\n"
					 "   © 1995 by  Karl Lukas\n\n"
					 "    Hinterzweienstr. 91\n"
					 "      CH-4132 Muttenz\n"
					 "        Switzerland\n\n"
					 "Email:\n\n"
					 "  kalle@gis.geogr.unizh.ch",
					 "Okay", NULL, NULL, ezRequestTags);
}

// --------------------------------------------------------------------------

BOOL LoadPreferences(struct AppPrefs *prefs)
{
	BPTR phandle = NULL;
	if (phandle = Open(PrefsName, MODE_OLDFILE))
	{
		LONG len = Read(phandle, prefs, sizeof (AppPrefs));
		Close(phandle);

		myPrefs.timer = FALSE;
		myPrefs.timerval = 0;
		if (len != sizeof (AppPrefs))
			return FALSE;
		else
			return TRUE;
	}
	else
		return FALSE;
}

BOOL SavePreferences(struct AppPrefs *prefs)
{
	BPTR phandle = NULL;

	prefs->windowX = DClockWnd->LeftEdge;
	prefs->windowY = DClockWnd->TopEdge;
	if (phandle = Open(PrefsName, MODE_NEWFILE))
	{
		LONG len = Write(phandle, prefs, sizeof (AppPrefs));
		Close(phandle);
		if (len != sizeof (AppPrefs))
			return FALSE;
		else
			return TRUE;
	}
	else
		return FALSE;
}

// --------------------------------------------------------------------------

BOOL OpenTimerDevice(void)
{
	if (TimerMP = CreatePort(0,0))
	{
		if (TimerIO = (struct timerequest *)
						  CreateExtIO(TimerMP, sizeof(struct timerequest)))
		{
			if (! (timerError = OpenDevice(TIMERNAME, UNIT_VBLANK,
											 (struct IORequest *)TimerIO, 0L)))
			{
				SetTimer(1);  // Delay min. 1 second
				return TRUE;
			}
		}

	}
	return FALSE;
}

void CloseTimerDevice(void)
{
	if (! timerError)
	{
		if (! (CheckIO((struct IORequest *)TimerIO)))
		{
			AbortIO((struct IORequest *)TimerIO);
		}
		WaitIO((struct IORequest *)TimerIO);
		CloseDevice((struct IORequest *)TimerIO);
	}
	if (TimerIO)
		DeleteExtIO((struct IORequest *)TimerIO);
	if (TimerMP)
		DeletePort(TimerMP);
}

void SetTimer(ULONG delay)
{
	TimerIO->tr_time.tv_secs = delay;     // Set delay
	TimerIO->tr_time.tv_micro = 0;
	TimerIO->tr_node.io_Command = TR_ADDREQUEST;
	SendIO((struct IORequest *)TimerIO);
}

// --------------------------------------------------------------------------

int Timeval2Seconds(int timeval)
{
	int hours, mins, seconds;

	hours = timeval / 10000;
	mins = (timeval - hours * 10000) / 100;
	seconds = (timeval - hours * 10000 - mins * 100);

	return hours * 3600 + mins * 60 + seconds;
}

int Seconds2Timeval(int secs)
{
	int hours, mins, seconds;

	hours = secs / 3600;
	mins = (secs - hours * 3600) / 60;
	seconds = (secs - hours * 3600 - mins * 60);

	return hours * 10000 + mins * 100 + seconds;
}

// --------------------------------------------------------------------------

BOOL IsChecked(int menuNumber)
{
	struct MenuItem *it;

	it = (struct MenuItem *)ItemAddress(DClockMenus, menuNumber);
	if (it->Flags & CHECKED)
		return TRUE;
	else
		return FALSE;
}


// --------------------------------------------------------------------------

BOOL AllocateParentSignals(void) /* This is called from parent process */
{
	BOOL ret = TRUE;


	if ((cleanupsignum = AllocSignal(-1)) == -1)  /* Allocate cleanupsig */
		ret = FALSE;
	else
		cleanupsig = 1L << cleanupsignum;

	if ((info_done_num = AllocSignal(-1)) == -1)  /* Allocate info_done */
		ret = FALSE;
	else
		info_done = 1L << info_done_num;

	if ((timercmdnum = AllocSignal(-1)) == -1)  /* Allocate timercmd */
		ret = FALSE;
	else
		timercmd = 1L << timercmdnum;

	if ((alarmcmdnum = AllocSignal(-1)) == -1)  /* Allocate alarmcmd */
		ret = FALSE;
	else
		alarmcmd = 1L << alarmcmdnum;

	return ret;
}


void FreeParentSignals(void)
{
	if (info_done_num != -1)
		FreeSignal(info_done_num);
	if (cleanupsignum != -1)
		FreeSignal(cleanupsignum);
	if (timercmdnum != -1)
		FreeSignal(timercmdnum);
	if (alarmcmdnum != -1)
		FreeSignal(alarmcmdnum);
}


BOOL AllocateChildSignals(void) /* This is called from child process */
{
	BOOL ret = TRUE;

	if (exitsignum = AllocSignal(-1) == -1)  /* Allocate exitsig */
		ret = FALSE;
	else
		exitsig = 1L << exitsignum;

	return ret;
}

void FreeChildSignals(void)
{
	if (exitsignum != -1)
		FreeSignal(exitsignum);
}

BOOL AllocateInfoSignals(void)
{
	BOOL ret = TRUE;

	if ((alarmsignum = AllocSignal(-1)) == -1)  /* Allocate alarmsig */
		ret = FALSE;
	else
		alarmsig = 1L << alarmsignum;

	if ((timersignum = AllocSignal(-1)) == -1)  /* Allocate timersig */
		ret = FALSE;
	else
		timersig = 1L << timersignum;

	if ((exit_info_num = AllocSignal(-1)) == -1)
		ret = FALSE;
	else
		exit_info = 1L << exit_info_num;

	return ret;
}

void FreeInfoSignals(void)
{
	if (alarmsignum != -1)
		FreeSignal(alarmsignum);
	if (timersignum != -1)
		FreeSignal(timersignum);
	if (exit_info_num != -1)
		FreeSignal(exit_info_num);
}


// --------------------------------------------------------------------------



void DClockTask(void)
{
	ULONG signal;
	ULONG timerSig;
	BOOL done = FALSE;

	if (OpenTimerDevice())
	{
		if (AllocateChildSignals())
		{
			timerSig = 1L << TimerMP->mp_SigBit;
			while (! done)
			{
				signal = Wait(timerSig | exitsig);
				if (signal & timerSig)
				{
					TimerMSG = GetMsg(TimerMP);
					SetTimer(1);
					RedrawTime(DClockWnd, &myPrefs);
				}
				if (signal & exitsig)
					done = TRUE;
			}
		}
		FreeChildSignals(); /* This is safe */
		CloseTimerDevice();
	}
	Signal(parenttask, cleanupsig);
	Wait(0);
}



void InfoTask(void)
{
	ULONG signal;
	BOOL done = FALSE;

	if (AllocateInfoSignals())
	{
		while (! done)
		{
			signal = Wait(alarmsig | timersig | exit_info);
			if (signal & alarmsig)
			{
				if (myPrefs.alrmcmd[0] != 0)
					Signal(parenttask, alarmcmd);
				ShowAlarm(&myPrefs);
			}
			if (signal & timersig)
			{
				if (myPrefs.timrcmd[0] != 0)
					Signal(parenttask, timercmd);
				ShowTimer(&myPrefs);
			}
			if (signal & exit_info)
				done = TRUE;
		}
	}
	FreeInfoSignals(); /* This is safe */
	Signal(parenttask, info_done);
	Wait(0);
}

// ----------------------------------------------------------------------

void SetCommand(int type)
{
	char buf[128];
	char buf2[32];

	struct TagItem tags[] =
	{
		RTGS_AllowEmpty, TRUE,
		RT_PubScrName, (ULONG)PubScreenName,
		TAG_DONE, 0
	};

	if (type == ALARM)
	{
		strcpy(buf2, "Alarm: ");
		strcpy(buf, myPrefs.alrmcmd);
	}
	else if (type == TIMER)
	{
		strcpy(buf2, "Timer: ");
		strcpy(buf, myPrefs.timrcmd);
	}
	strcat(buf2, "Enter command string");

	if (rtGetStringA((UBYTE *)buf, 128, buf2, NULL, tags))
	{
		if (type == ALARM)
			strcpy(myPrefs.alrmcmd, buf);
		else if (type == TIMER)
			strcpy(myPrefs.timrcmd, buf);
	}
}

// ----------------------------------------------------------------------------

int myArgInt(char **tooltypes, char *tool, int dfault)
{
	int j, i = 0;
	char *tval;

	if (tval = (char *)FindToolType((UBYTE **)tooltypes, tool))
		return atoi(tval);
	else
		return dfault;
}

char *myArgString(char **tooltypes, char *tool, char *dfault)
{
	int j, i = 0;
	char *tval;

	if (tval = (char *)FindToolType((UBYTE **)tooltypes, tool))
		return tval;
	else
		return dfault;
}

BOOL myArgBool(char **tooltypes, char *tool, BOOL dfault)
{
	int j, i = 0;
	char *tval;

	if (tval = (char *)FindToolType((UBYTE **)tooltypes, tool))
	{
		if (*tval == 'n' || *tval == 'N')
			return FALSE;
		if (*tval == 'y' || *tval == 'Y')
			return TRUE;
		/* else: Error, wrong argument */
	}
	return dfault;
}
 
// ----------------------------------------------------------------------------

BOOL DoAppIcon(void)
{
	struct DiskObject   *dobj = NULL;
	struct MsgPort   *msgport = NULL;
	struct AppIcon   *appicon = NULL;
	struct AppMessage *appmsg = NULL;
	BOOL ret = FALSE;

	if (dobj = GetDiskObjectNew(DiskObjectName))
	{
		dobj->do_Type = NULL;
		if (msgport = CreateMsgPort())
		{
			if (appicon = AddAppIconA(0l, 0L, "DClock", msgport, NULL, dobj, NULL))
			{
				WaitPort(msgport);
				RemoveAppIcon(appicon); 
				while(appmsg = (struct AppMessage *)GetMsg(msgport))
					ReplyMsg((struct Message *)appmsg);
				ret = TRUE;
			}
			DeleteMsgPort(msgport);
		}
		FreeDiskObject(dobj);
	}
	return ret;
}
 
