/**
 * HelloWorld - for Palm!
 *
 * This source file contains the code for a very simple Palm OS application.
 * It's purpose is to describe at a high, simple level the process of developing
 * a Palm application.
 *
 * The resource file HelloWorld.rcp contains PilRC resource descriptions for
 * the main form, and also the alert window that pops and says hello.
 *
 * The first included file is PalmOS.h. This file is provided with the PalmOS
 * SDK, and includes most (if not all) of the functionality needed to write
 * a Palm application. In rare cases, you may need to include certain other files
 * yourself, but this is a very rare case.
 *
 * One very important thing to note if this is your first palm application is the
 * use of data types. Instead of using standard c types int, and char,
 * the SDK has defined their own types to use instead, Int16, Int32, Char, etc.... 
 * While you may still use standard c types successfully, it is better to rely on the 
 * Palm OS defined types incase they should ever change their representation of the data.
 */

#include "PalmOS.h"
#include "HelloWorld.h"

///////////////////////////////////////////////////////////////////////////////////////////
// Function Prototypes....

static void EventLoop( );
static Boolean ApplicationHandleEvent( EventPtr event );
static Boolean MainFormEventHandler( EventPtr event );

/*******************************************************************************************
 * PilotMain
 * ---------
 *
 * In PalmOS programming, PilotMain serves as the launching point for any application.
 * It's main purpose is to interpret the launchcodes passed in from the operating system
 * and respond appropriately. The most useful launch code is sysAppLaunchCmdNormalLaunch.
 * As you can see below, this is the only launch code HelloWorld responds to. In many more
 * copmlex applications, your program can be made more "Palm-Friendly" by responding to a
 * variety of other launch codes as well.
 *
 * Our main function reacts to sysAppLaucnhCmdNormalLaunch by loading the main form into
 * memory, displaying it, and then starting the event loop.
 *******************************************************************************************/
UInt32 PilotMain( UInt16 launchCode, MemPtr cmdPBP, UInt16 launchFlags )
{
	Err err;
	
	switch ( launchCode )
	{
		case sysAppLaunchCmdNormalLaunch:
			FrmGotoForm( MainForm );
			EventLoop();
			err = 0;
		break;

		default: break;
	}

	return err;
}

/********************************************************************************************
 * EventLoop
 * ---------
 *
 * This is the main event loop. Any Palm application that interacts with the user will need
 * to have one. It's purpose is to wait for notification from the operating system of an
 * event, and then dispatch that event to the proper handler.
 * 
 * Events can be generated by either the user, or the operating system. Any time a user taps
 * on the silkscreen or presses a button, an event is generated. System events are generated
 * indirectly by the user, and passed to the application in the same manner. For instance, if
 * the user were to switch to the Address Book application while using your application, PalmOS
 * would send your application an appStopEvent message, causing your program to exit.
 *
 * Notice the order in which the event handlers are called. First is SysHandleEvent, then 
 * ApplicationHandleEvent, and finally FrmDispatchEvent. SysHandleEvent should always be
 * called first so that your application does not mis-interpret and mishandle an event that
 * wasn't meant for it. This also gives priority to the operating system over the applications,
 * which seems logical enough. Next is ApplicationHandleEvent. This is a programmer-defined
 * method that handles events such as loading forms. Finally is the FrmDispatchEvent method.
 *
 * This method is defined by the operating system for you. When a form is loaded into memory
 * by the application event handler, it is assigned to a function, called a callback function.
 * This callback function is executed every time the form is given an event to handle. 
 * FrmDispatchEvent's job is to lookup the active form, and pass the event to it.
 **************************************************************************************************/
static void EventLoop( )
{
	EventType event;
	UInt16    error;

	do
	{
		EvtGetEvent( &event, evtWaitForever );
		if (! SysHandleEvent( &event ) )
			if ( ! ApplicationHandleEvent( &event ) )
				FrmDispatchEvent( &event );
	} while ( event.eType != appStopEvent );
}

/******************************************************************************************************
 * MainFormEventHandler
 * --------------------
 *
 * This is the callback function that handles all events generated on the MainForm. When main form is loaded
 * into memory, the ApplicationHandleEvent assigns it to this method so that it's events can be handled properly.
 ********************************************************************************************************/
static Boolean MainFormEventHandler( EventPtr event )
{
	FormType *form;
	Boolean handled = false;

	switch( event->eType )
	{
		case frmOpenEvent:
			form = FrmGetActiveForm();
			
			FrmDrawForm( form );
			FrmSetFocus( form, FrmGetObjectIndex( form, MainField ) );
			handled = true;
		break;
		case ctlSelectEvent:
			if ( event->data.ctlSelect.controlID == MainButton )
			{
				FieldType *field;
				Char * text;

				form = FrmGetActiveForm();
				field = FrmGetObjectPtr( form, FrmGetObjectIndex( form, MainField ) );

				text = FldGetTextPtr( field );
				FrmCustomAlert( HelloAlert, text, NULL, NULL );			
			}

		default:
		break;
	}

	return handled;
}

/************************************************************************************************************
 * ApplicationHandleEvent
 * ----------------------
 *
 * This is the application's event handler. It's primary job is to handle events that effect the whole
 * application, not just the state of one form. For instance, loading a form into memory is an application
 * wide event. 
 ***********************************************************************************************************/
static Boolean ApplicationHandleEvent( EventPtr event )
{
	FormType *form;
	UInt16 formID;
	Boolean handled = false;

	if ( event->eType == frmLoadEvent )
	{
		formID = event->data.frmLoad.formID;
		form = FrmInitForm( formID );
		FrmSetActiveForm( form );

		switch( formID )
		{
			case MainForm:
				FrmSetEventHandler( form, MainFormEventHandler );
				break;
			default:
				break;
		}

		handled = true;
	}

	return handled;
}