

/* WristRest - v0.1 isb@pobox.com, 7 Jan 1996. Cold and Grey */
 
#include <Pilot.h>				// all the system toolbox headers
#include <SoundMgr.h>


#include "WristRsc.h"		// application resource defines


/***********************************************************************
 * Prototypes for internal functions
 **********************************************************************/
static void StartApplication(void);
static Boolean MainFormHandleEvent(EventPtr event);
static void EventLoop(void);
static void CheckUI();

static char workStr[20] = "";
static char breakStr[20] = "";

static int minCount = 0;
static char minStr[30] = "0 minutes left";

static char stoppedStr[30] = "Press START & begin work";
static char workingStr[30] = "You should be WORKING!!!";
static char restingStr[30] = "         Take a BREAK!!!";
int x = 30;
int y = 120;

static void SetPrefs(int workP, int breakP, int version);
static void UpdatePrefs();

static UInt cardNo;
LocalID appID;

typedef struct
	{
		int workPeriod;
		int breakPeriod;
		int version;
	} WristPreferenceType;
	
WristPreferenceType prefs;

static void SetPrefs(int workP, int breakP, int version)
{
	prefs.workPeriod = workP;
	prefs.breakPeriod = breakP;
	prefs.version = version;
}

static void UpdatePrefs()
{
	PrefSetAppPreferences('Wris', 1, &prefs, sizeof(WristPreferenceType));
}

static void StartApplication(void)
{
	FormPtr	frm;
	FieldPtr workPtr, breakPtr;

	// Initialize and draw the main memo pad form.
	frm = FrmInitForm(mainForm);	
	FrmSetActiveForm(frm);
		
	FrmDrawForm(frm);

	if (PrefGetAppPreferences('Wris', 1, &prefs, sizeof(WristPreferenceType)) == NULL)
		SetPrefs(30,5,0);
		
	//Clear any existing alarms we've got
	AlmSetAlarm(cardNo, appID, 0, 0, 0);

	WinDrawChars(stoppedStr, StrLen(stoppedStr), x, y);
	WinDrawChars("i", 1, 153, 0);
	
	SysCurAppDatabase(&cardNo, &appID);
	
	//Put old text values back onto screen
	workPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainWorkField))));
	breakPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainBreakField))));
 
 	StrIToA(workStr, prefs.workPeriod);
 	StrIToA(breakStr, prefs.breakPeriod);
	FldInsert(workPtr, workStr, StrLen(workStr));
	FldInsert(breakPtr, breakStr, StrLen(breakStr));

	FldSetDirty(workPtr, false);
	FldSetDirty(breakPtr, false);
}

void CheckUI()
{
	FormPtr frm;
	FieldPtr workPtr, breakPtr;
	int tempWork, tempBreak;
					
	//Update the values from the UI...
	frm = FrmGetActiveForm();
	workPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainWorkField))));
	breakPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainBreakField))));
 
 	if (FldGetTextPtr(workPtr) == NULL)
 		tempWork = 0;
 	else
 		tempWork = StrAToI(FldGetTextPtr(workPtr));

 	if (FldGetTextPtr(breakPtr) == NULL)
 		tempBreak = 0;
 	else
 		tempBreak = StrAToI(FldGetTextPtr(breakPtr));

	if (tempWork < 0)
		tempWork = 0;
		
	if (tempBreak < 0)
		tempBreak = 0;
		
 	SetPrefs(tempWork, tempBreak, 1);
 	UpdatePrefs();
}

/***********************************************************************
 *
 * FUNCTION:		MainFormHandleEvent
 *
 * DESCRIPTION:	Handles processing of events for the ÒmainÓ form.
 *
 * PARAMETERS:		event	- the most recent event.
 *
 * RETURNED:		True if the event is handled, false otherwise.
 *
 ***********************************************************************/
static Boolean MainFormHandleEvent(EventPtr event)
{
		Boolean		handled = false;

		if (event->eType == nilEvent)
		{		
			ULong nowTime, alarmTime;
			DWord ref=0;
			int tempCnt;
			
			//Lets look at the clock and see if we're on a new minute
			nowTime = TimGetSeconds();
			alarmTime = AlmGetAlarm(cardNo, appID, &ref);	
			if (alarmTime)
			{
				tempCnt  = ((alarmTime - nowTime) / 60) + 1;
				
				if (tempCnt != minCount)
				{
					minCount = tempCnt;
					WinEraseChars(minStr, StrLen(minStr), x+20, y+15);
				 	StrIToA(minStr, minCount);
				 	if (minCount==1)
				 		StrCat(minStr, " minute left  ");
				 	else
				 		StrCat(minStr, " minutes left ");
				 					
					WinDrawChars(minStr, StrLen(minStr), x+20, y+15);
				}
			}
		}
 	 	if (event->eType == ctlSelectEvent)		// P2. process menu events for this form
		{
		
			FormPtr frm;
			ULong alarmTime;
			
			if (event->data.ctlEnter.controlID == startButton)
			{	
				FormPtr frm;
				FieldPtr fld;
				FieldAttrType fldAttr;
				
 				CheckUI();
 				
				//Cancel any alarm...
				AlmSetAlarm(cardNo, appID, 0, 0, 0);
			
				//Set a new alarm for now + workPeriod...
				alarmTime = (prefs.workPeriod * 60) + TimGetSeconds();
				AlmSetAlarm(cardNo, appID, 1, alarmTime, 0);
				WinEraseChars(stoppedStr, StrLen(stoppedStr), x, y);
				WinDrawChars(workingStr, StrLen(workingStr), x, y);

				//Set the fields not editable
				frm = FrmGetActiveForm();
				fld = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainWorkField))));
				FldGetAttributes(fld, &fldAttr);
				fldAttr.editable = 0;
				FldSetAttributes(fld, &fldAttr);
				fld = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainBreakField))));
				FldGetAttributes(fld, &fldAttr);
				fldAttr.editable = 0;
				FldSetAttributes(fld, &fldAttr);
				
				handled = true;			
			}
			else
			if (event->data.ctlEnter.controlID == stopButton)
			{		
				FormPtr frm;
				FieldPtr fld;
				FieldAttrType fldAttr;
				
				CheckUI();
					
				//Cancel any alarm...
				AlmSetAlarm(cardNo, appID, 0, 0, 0);
				WinEraseChars(minStr, StrLen(minStr), x+20, y+15);
				WinEraseChars(workingStr, StrLen(workingStr), x, y);
				WinDrawChars(stoppedStr, StrLen(stoppedStr), x, y);

				//Set the fields editable
				frm = FrmGetActiveForm();
				fld = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainWorkField))));
				FldGetAttributes(fld, &fldAttr);
				fldAttr.editable = 1;
				FldSetAttributes(fld, &fldAttr);
				fld = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainBreakField))));
				FldGetAttributes(fld, &fldAttr);
				fldAttr.editable = 1;
				FldSetAttributes(fld, &fldAttr);

				handled = true;			
			}
		} 

	return(handled);
}

/***********************************************************************
 *
 * FUNCTION:		EventLoop
 *
 * DESCRIPTION:	A simple loop that obtains events from the Event
 *						Manager and passes them on to various applications and
 *						system event handlers before passing them on to
 *						FrmHandleEvent for default processing.
 *
 * PARAMETERS:		None.
 *
 * RETURNED:		Nothing.
 *
 ***********************************************************************/
static void EventLoop(void)
{
	EventType	event;
	Word			error;
	
	do
		{
		// Get the next available event.
//		EvtGetEvent(&event, evtWaitForever);
		EvtGetEvent(&event, sysTicksPerSecond * 10000); //Not too often I hope...
		
		// Give the system a chance to handle the event.
		if (! SysHandleEvent (&event))

			// P2. Give the menu bar a chance to update and handle the event.	
			if (! MenuHandleEvent(NULL, &event, &error))

				// Give the application a chance to handle the event.
				if (! MainFormHandleEvent(&event))
	
					// Let the form object provide default handling of the event.
					FrmHandleEvent(FrmGetActiveForm(), &event);
		} 
	while (event.eType != appStopEvent);
								// ** SPECIAL NOTE **
								// In order for the Emulator to exit
								// cleanly when the File|Quit menu option is
								// selected, the running application
								// must exit.  The emulator will generate an 
								// ÒappStopEventÓ when Quit is selected.
}


/***********************************************************************
 *
 * FUNCTION:		PilotMain
 *
 * DESCRIPTION:	This function is the equivalent of a main() function
 *						in standard ÒCÓ.  It is called by the Emulator to begin
 *						execution of this application.
 *
 * PARAMETERS:		cmd - command specifying how to launch the application.
 *						cmdPBP - parameter block for the command.
 *						launchFlags - flags used to configure the launch.			
 *
 * RETURNED:		Any applicable error code.
 *
 ***********************************************************************/
DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
{

	if (cmd == sysAppLaunchCmdNormalLaunch)
	{
	
		//We've just been called
		
		// Set up initial form.
		StartApplication();
		
		// Start up the event loop.
		EventLoop();
	
		CheckUI();	
		
		//Cancel any lingering alarms...
		AlmSetAlarm(cardNo, appID, 0, 0, 0);		
	}
	else
	if (cmd == sysAppLaunchCmdAlarmTriggered)
	{
		DWord ref;
		ULong forUs;
		ULong alarmTime;
		
		ref = ((SysAlarmTriggeredParamType *)cmdPBP)->ref;
		
		if (!ref)
		{
			WinDrawChars("Boo!", 4, 30, 30);
			return 0;
		}
			
		if (ref == 1) //The end of work time
		{
			//Cancel any alarm...
			AlmSetAlarm(cardNo, appID, 0, 0, 0);
		
			//Set a new alarm for now + breakPeriod...
			alarmTime = (prefs.breakPeriod * 60) + TimGetSeconds();
			AlmSetAlarm(cardNo, appID, 2, alarmTime, 0);	
			
			//Tell us to take a break!
			WinEraseChars(minStr, StrLen(minStr), x+20, y+15);
			WinEraseChars(workingStr, StrLen(workingStr), x, y);
			WinDrawChars(restingStr, StrLen(restingStr), x, y);
			SndPlaySystemSound(sndAlarm);
		}
		else
		if (ref == 2)
		{
			//Cancel any alarm...
			AlmSetAlarm(cardNo, appID, 0, 0, 0);
		
			//Set a new alarm for now + workPeriod...
			alarmTime = (prefs.workPeriod * 60) + TimGetSeconds();
			AlmSetAlarm(cardNo, appID, 1, alarmTime, 0);
			WinEraseChars(minStr, StrLen(minStr), x+20, y+15); 
			WinEraseChars(restingStr, StrLen(restingStr), x, y);
			WinDrawChars(workingStr, StrLen(workingStr), x, y);
			SndPlaySystemSound(sndAlarm);
		}
	}
		
	return(0);

}



