

/***********************************************************************
 *
 *	Copyright © Palm Computing 1995 -- All Rights Reserved
 *
 * PROJECT: Memo Pad Sample Application
 *
 * FILE: MemoPad.c (Phase 1)
 *
 * DESCRIPTION: Sample application to demonstrate the various
 * 	features available.
 *
 *	OBJECTIVE: Create an initial main form with a title and an
 * 	exit button.
 *
 * REVISION HISTORY:
 * 	 9/1/95	David		Initial version
 *
 **********************************************************************/
 
#include <Pilot.h>				// all the system toolbox headers
#include <FloatMgr.h>

#include "CurrExRsc.h"		// application resource defines


/***********************************************************************
 * Prototypes for internal functions
 **********************************************************************/
static void StartApplication(void);
static Boolean MainFormHandleEvent(EventPtr event);
static void EventLoop(void);
static Boolean CalculateTarget();
static Boolean CalculateHome();

Handle rateHandle;
Handle targetHandle;
Handle homeHandle;

//char targetStr[20] = "";
//char homeStr[20] = "";

static Boolean InRateField = false;
static Boolean InHomeField = false;
static Boolean InTargetField = false;

static void SetPrefs(char *rate, char *target, char *home);
static void UpdatePrefs();

typedef struct
	{
		Char rate[22];
		Char target[22];
		Char home[22];
	} CurrExPreferenceType;
	
CurrExPreferenceType prefs;

static void SetPrefs(char *rate, char *target, char *home)
{
	StrCopy(prefs.rate, rate);
	StrCopy(prefs.target, target);
	StrCopy(prefs.home, home);
}

static void UpdatePrefs()
{
	FormPtr	frm;
	FieldPtr ratePtr, targetPtr, homePtr;

	frm = FrmGetFirstForm();	

	ratePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainRateField))));
	homePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainHomeField))));
	targetPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainTarget0Field))));

	StrCopy(prefs.rate, FldGetTextPtr(ratePtr));
	StrCopy(prefs.target, FldGetTextPtr(targetPtr));
	StrCopy(prefs.home, FldGetTextPtr(homePtr));

	PrefSetAppPreferences('Curr', 1, &prefs, sizeof(CurrExPreferenceType));
}

/***********************************************************************
 *
 * FUNCTION:     StartApplication
 *
 * DESCRIPTION:  This routine sets up the initial state of the application.
 *
 * PARAMETERS:   None.
 *
 * RETURNED:     Nothing.
 *
 ***********************************************************************/
static void StartApplication(void)
{
	FormPtr	frm;
	FieldPtr ratePtr, targetPtr, homePtr;
	CharPtr targetText, rateText, homeText;

	rateHandle = MemHandleNew(20+1);
	targetHandle = MemHandleNew(20 + 1);
	homeHandle = MemHandleNew(20 + 1);

	// Initialize and draw the main memo pad form.
	frm = FrmInitForm(mainForm);	
	FrmSetActiveForm(frm);
		
	FrmDrawForm(frm);

	if (PrefGetAppPreferences('Curr', 1, &prefs, sizeof(CurrExPreferenceType)) == NULL)
		SetPrefs("0", "0", "0");

	//Put old text values back onto screen
	ratePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainRateField))));
	homePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainHomeField))));
	targetPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainTarget0Field))));
 
	FldInsert(ratePtr, prefs.rate, StrLen(prefs.rate));
	FldInsert(homePtr, prefs.home, StrLen(prefs.home));
	FldInsert(targetPtr, prefs.target, StrLen(prefs.target));

	FldSetDirty(ratePtr, false);
	FldSetDirty(homePtr, false);
	FldSetDirty(targetPtr, false);
	
	CalculateTarget();
	CalculateHome();
}

/***********************************************************************
 *
 * 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 == ctlSelectEvent)		// P2. process menu events for this form
		{
		
			FormPtr frm;
			FieldPtr ratePtr;
			FieldPtr homePtr;
			FieldPtr target0Ptr;
			
			if (event->data.ctlEnter.controlID == clearButton)
			{
				// clear button was pressed
				frm = FrmGetFormPtr(mainForm);
				
				//Clear all the boxes
				ratePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainRateField))));		
				FldFreeMemory(ratePtr);
				FldInsert(ratePtr, "0", StrLen("0"));
				FldSetDirty(ratePtr, true);
								
				homePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainHomeField))));
				FldFreeMemory(homePtr);
				FldInsert(homePtr, "0", StrLen("0"));
				FldSetDirty(homePtr, true);

				target0Ptr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainTarget0Field))));
				FldFreeMemory(target0Ptr);
				FldInsert(target0Ptr, "0", StrLen("0"));
				FldSetDirty(target0Ptr, true);
					
				FrmDrawForm(frm);	
				UpdatePrefs();
				CalculateTarget();
				CalculateHome();
				
				handled = true;			
			}
		} 
	 else
 	 if (event->eType == fldEnterEvent)
 	 {
 	 		//Are we going to change the rate?
 	 		if (event->data.fldEnter.fieldID == mainRateField)
 	 		{
 	 			InRateField = true;
 	 			InHomeField = false;
 	 			InTargetField = false;
 	 		}
 	 		else
 	 		if (event->data.fldEnter.fieldID == mainTarget0Field)
 	 		{
 	 			InTargetField = true;
 	 			InRateField = false;
 	 			InHomeField = false;
 	 		}
 	 		else
 	 		if (event->data.fldEnter.fieldID == mainHomeField)
 	 		{
 	 			InHomeField = true;
 	 			InRateField = false;
 	 			InTargetField = false;
 	 		}
 	 		else
			{
	 			InHomeField = false;
 	 			InRateField = false;
 	 			InTargetField = false;
			} 	 		
	 }
	 else
	 if (event->eType == keyDownEvent)
	 {

	 		if ( InRateField || InHomeField || InTargetField)
	 		{
	 		
	 	 		//What's the key?
		 		if (  ( (event->data.keyDown.chr >= 0x30) && (event->data.keyDown.chr <= 0x39) )
		 			 ||(event->data.keyDown.chr == 0x2e) || (event->data.keyDown.chr == 0x08) )
				{				
					//Let the system handle this first
					FrmHandleEvent(FrmGetActiveForm(), event);

		 		 	if (InRateField || InHomeField)
 	 					CalculateTarget();
				
					if (InRateField || InTargetField)
		 		 		CalculateHome();	
		 		 		 		 		
	 				UpdatePrefs();
 		 		
 	 			}
 	 				
 	 			handled = true;
	 		}
	 }

	return(handled);
}

static Boolean CalculateTarget()
{
	FormPtr frm;
	FieldPtr ratePtr;
	FieldPtr homePtr;
	FieldPtr targetPtr;
	
	CharPtr targetText;
	char targetStr[20];
	char tempStr[20];
	CharPtr e;
	CharPtr dp;
	CharPtr rateStr;
	CharPtr hStr;

	frm = FrmGetFormPtr(mainForm);
				
	if (frm != NULL)
	{												
		FloatType rate;
		FloatType home;
		FloatType target;
		int doneDec;
		int decimal;
		int i;
												
		ratePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainRateField))));
		homePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainHomeField))));
		targetPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainTargetField))));

		if ( (FldGetTextLength(ratePtr) == 0) || (FldGetTextLength(homePtr) == 0) )
		{
			targetText = MemHandleLock(targetHandle);
			StrCopy(targetText, "0");
			MemHandleUnlock(targetHandle);	
			FldSetTextHandle(targetPtr, targetHandle);
			FldDrawField(targetPtr);
			return true;
		}
	
		rateStr = FldGetTextPtr(ratePtr);
		hStr = FldGetTextPtr(homePtr);
				
		
		if (	( (rateStr == NULL) || (StrLen(rateStr) == 0) || (!StrCompare(rateStr, "0")) )
			 || ( (hStr == NULL) || (StrLen(hStr) == 0) || (!StrCompare(hStr, "0")) ) )
		{
			targetText = MemHandleLock(targetHandle);
			StrCopy(targetText, "0");
			MemHandleUnlock(targetHandle);	
			FldSetTextHandle(targetPtr, targetHandle);
			FldDrawField(targetPtr);
			return true;
		}

		FplInit();
		rate = FplAToF(rateStr);
		home = FplAToF(hStr);
		
		target = FplMul(rate, home);

/*
		if (FplFloatToLong(target) == 0)
		{
			targetText = MemHandleLock(targetHandle);
			StrCopy(targetText, "?");
			MemHandleUnlock(targetHandle);	
			FldSetTextHandle(targetPtr, targetHandle);
			FldDrawField(targetPtr);
			FplFree();
			return true;
		}												
*/

		FplFToA(target, targetStr);
						
		FplFree();
						
		//Format string

						// targetStr contains too many dp's - lets strip them...
						// We also need  to convert 'e' into real numbers
						
						e = StrChr(targetStr, 'e');
						e[0] = '\0';
						
						e++;
						
						decimal = StrAToI(e);
						
						//There's a bug here!
						if (decimal < 0)
						{
							// A number that is less than 1
							if (decimal == -1)
							{								
								tempStr[0]='0';
								tempStr[1]='.';
								tempStr[2]=targetStr[0];
								tempStr[3]=targetStr[2];
								tempStr[4]='\0';								
							}
							else
							if (decimal == -2)
							{
								tempStr[0]='0';
								tempStr[1]='.';
								tempStr[2]='0';
								tempStr[3]=targetStr[0];
								tempStr[4]='\0';
							}
							else
							{
								//We don't care anymore, its zero to 2dp!
								StrCopy(tempStr, "0.00"); //Actually it may be .01!
							}
						}
						else
						{
							// point needs to move 'decimal' places right
							tempStr[0] = targetStr[0];
						
							doneDec =1;
							for (i=2;i<=StrLen(targetStr)+1;i++)
							{
								if ((i-2)==decimal)
								{
									tempStr[i-doneDec] = '.';
									doneDec = 0;
								}	 
								tempStr[i-doneDec] = targetStr[i];
							}						
											
							dp = StrChr(tempStr, '.');
							if (dp != NULL)
									dp[3] = '\0';
							else
								StrCopy(tempStr, "Too many!");
						}			
						
		targetText = MemHandleLock(targetHandle);
		StrCopy(targetText, tempStr);
		MemHandleUnlock(targetHandle);
		
		// Set the field's text to the data in the new memory chunk.
		FldSetTextHandle(targetPtr, targetHandle);

		FldDrawField(targetPtr);				
	}

	return true;
}

static Boolean CalculateHome()
{
	FormPtr frm;
	FieldPtr ratePtr;
	FieldPtr homePtr;
	FieldPtr targetPtr;

	CharPtr homeText;
	CharPtr targStr;
	char homeStr[20];
	char tempStr[20];
	CharPtr e;
	CharPtr dp;
	CharPtr rateStr;

	frm = FrmGetFormPtr(mainForm);
				
	if (frm != NULL)
	{																		
		FloatType rate;
		FloatType home;
		FloatType target;
		int doneDec;
		int decimal;
		int i;
						
						
		ratePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainRateField))));
		homePtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainHome0Field))));
		targetPtr = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, mainTarget0Field))));
		
		if ( (FldGetTextLength(ratePtr) <= 0) || (FldGetTextLength(targetPtr) <= 0) )
		{
			homeText = MemHandleLock(homeHandle);
			StrCopy(homeText, "0");
			MemHandleUnlock(homeHandle);
			FldSetTextHandle(homePtr, homeHandle);
			FldDrawField(homePtr);
			return true;
		}
		
		rateStr = FldGetTextPtr(ratePtr);
		targStr = FldGetTextPtr(targetPtr);
		
		if ( ( (rateStr == NULL) || (StrLen(rateStr) == 0) || (!StrCompare(rateStr, "0")) )
			|| ( (targStr == NULL) || (StrLen(targStr) == 0) || (!StrCompare(targStr, "0")) ) )
		{
			homeText = MemHandleLock(homeHandle);
			StrCopy(homeText, "0");
			MemHandleUnlock(homeHandle);
			FldSetTextHandle(homePtr, homeHandle);
			FldDrawField(homePtr);
			return true;
		}

		FplInit();
		target = FplAToF(targStr);
		rate = FplAToF(rateStr);

/*
		if ( (FplFloatToLong(rate) == 0) || (FplFloatToLong(target) == 0) )
		{
			homeText = MemHandleLock(homeHandle);
			StrCopy(homeText, "X");
			MemHandleUnlock(homeHandle);
			FldSetTextHandle(homePtr, homeHandle);
			FldDrawField(homePtr);
			FplFree();
			return true;
		}
*/
		home = FplDiv(target, rate);		

		FplFToA(home, homeStr);
				
		FplFree();
						
		// homeStr contains too many dp's - lets strip them...
		// We also need  to convert 'e' into real numbers
						
						e = StrChr(homeStr, 'e');
						e[0] = '\0';
						
						e++;
						
						decimal = StrAToI(e);
						
						//There's a bug here!
						if (decimal < 0)
						{
							// A number that is less than 1
							if (decimal == -1)
							{								
								tempStr[0]='0';
								tempStr[1]='.';
								tempStr[2]=homeStr[0];
								tempStr[3]=homeStr[2];
								tempStr[4]='\0';
							}
							else
							if (decimal == -2)
							{
								tempStr[0]='0';
								tempStr[1]='.';
								tempStr[2]='0';
								tempStr[3]=homeStr[0];
								tempStr[4]='\0';
							}
							else
							{
								//We don't care anymore, its zero to 2dp!
								StrCopy(tempStr, "0.00"); //Actually it may be .01!
							}
						}
						else
						{
							// point needs to move 'decimal' places right
							tempStr[0] = homeStr[0];
						
							doneDec =1;
							for (i=2;i<=StrLen(homeStr)+1;i++)
							{
								if ((i-2)==decimal)
								{
									tempStr[i-doneDec] = '.';
									doneDec = 0;
								}	 
								tempStr[i-doneDec] = homeStr[i];
							}						
											
							dp = StrChr(tempStr, '.');
							if (dp != NULL)
									dp[3] = '\0';
							else
								StrCopy(tempStr, "Error");
						}			

		homeText = MemHandleLock(homeHandle);
		StrCopy(homeText, tempStr);
		MemHandleUnlock(homeHandle);
		
		// Set the field's text to the data in the new memory chunk.
		FldSetTextHandle(homePtr, homeHandle);
				
		FldDrawField(homePtr);
}


	return true;
}

/***********************************************************************
 *
 * 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);
		
		// 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)
	{
		// Set up initial form.
		StartApplication();
		
		// Start up the event loop.
		EventLoop();
		
		UpdatePrefs();

	}
		
	return(0);

}



