760 lines
18 KiB
C
760 lines
18 KiB
C
/***************************************************************
|
|
*
|
|
* Project:
|
|
* HelperReceiver
|
|
*
|
|
* Copyright info:
|
|
* Copyright (c) Handspring 1999 -- All Rights Reserved
|
|
*
|
|
* FileName:
|
|
* HelperReceiver.c
|
|
*
|
|
* Description:
|
|
* A sample test application to demonstrate to to register
|
|
* and received SMS, Email, and WEB system helper notifications.
|
|
*
|
|
* History:
|
|
* 18-apr-2000 dia Created
|
|
* 24-may-2000 vmk Modified for the semi-final Helpers API
|
|
* 20-jul-2000 jem Modified from MailWrapper to simulate phone usage.
|
|
* 06-sep-2000 sv Modified to conform to new Helper Services API.
|
|
* 14-oct-2003 fhv Modified to build under Palm OS 5 SDK.
|
|
* 18-oct-2003 fhv Added Email and WEB processing to release a sample code
|
|
* for DTS (developers).
|
|
****************************************************************/
|
|
|
|
#include <PalmOS.h>
|
|
|
|
#include <68K/Hs.h>
|
|
|
|
#include <Helper.h>
|
|
#include <HelperServiceClass.h>
|
|
#include <HsNav.h>
|
|
|
|
#include "HelperReceiver.h"
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Private Equates
|
|
*
|
|
***********************************************************************/
|
|
|
|
//Crazy mod to the file to get it to compile - this is actually registered
|
|
//in HsCreators.h, but would cause registration trouble with the other phone
|
|
//incs directory
|
|
|
|
#define HelperReceiverCreator 'TRHR'
|
|
|
|
#define prvMyHelperID HelperReceiverCreator
|
|
|
|
// Until the new Helper Service Classes are defined, we define them here
|
|
// so implementation for the Default Apps panel can continue. Remove these
|
|
// service class ID definitions when HelperServiceClass.h has been updated.
|
|
#define kHelperServiceClassIDURL 'url_'
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Global variables
|
|
*
|
|
***********************************************************************/
|
|
|
|
|
|
static void
|
|
DoRegister (void)
|
|
{
|
|
UInt16 cardNo;
|
|
LocalID dbID;
|
|
Err err;
|
|
|
|
// Get information about this application to send to Notification
|
|
// manager calls...
|
|
SysCurAppDatabase (&cardNo, &dbID);
|
|
|
|
err = SysNotifyRegister (cardNo, dbID, sysNotifyHelperEvent,
|
|
NULL /*callbackP*/,
|
|
sysNotifyNormalPriority,
|
|
NULL /*userDataP*/);
|
|
|
|
// add another scenario: register successfully.
|
|
if (err == errNone)
|
|
FrmCustomAlert (rscRegisterSuccessAlertID, "YES!", "", "");
|
|
|
|
if (err == sysNotifyErrDuplicateEntry)
|
|
{
|
|
FrmCustomAlert (rscRegisterFailedAlertID, "App already registered", "", "");
|
|
}
|
|
else if (err)
|
|
{
|
|
Char buffer[32];
|
|
StrIToH (buffer, err);
|
|
FrmCustomAlert (rscRegisterFailedAlertID, "Err: 0x", buffer, "");
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
DoUnregister (void)
|
|
{
|
|
UInt16 cardNo;
|
|
LocalID dbID;
|
|
Err err;
|
|
|
|
// Get information about this application to send to Notification
|
|
// manager calls...
|
|
SysCurAppDatabase (&cardNo, &dbID);
|
|
|
|
err = SysNotifyUnregister (cardNo, dbID, sysNotifyHelperEvent,
|
|
sysNotifyNormalPriority);
|
|
|
|
// add another scenario: register successfully.
|
|
if (err == errNone)
|
|
FrmCustomAlert (rscUnregisterSuccessAlertID, "YES!", "", "");
|
|
|
|
if (err == sysNotifyErrEntryNotFound)
|
|
{
|
|
FrmCustomAlert (rscUnregisterFailedAlertID, "App was not registered", "", "");
|
|
}
|
|
else if (err)
|
|
{
|
|
Char buffer[32];
|
|
StrIToH (buffer, err);
|
|
FrmCustomAlert (rscUnregisterFailedAlertID, "Err: 0x", buffer, "");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************
|
|
* Function: MainFrmInit
|
|
*
|
|
* Summary: This routine initializes the "Main View" of our app
|
|
*
|
|
* Parameters:
|
|
* frmP IN form pointer
|
|
*
|
|
* Returns:
|
|
* void
|
|
*
|
|
* Called By:
|
|
* MainFrmEventHandler()
|
|
*
|
|
* Notes:
|
|
*
|
|
* History:
|
|
* 18-apr-2000 dia Ceated
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
MainFrmInit (FormPtr frmP)
|
|
{
|
|
;
|
|
}
|
|
|
|
|
|
/***************************************************************
|
|
* Function: MainFrmDoCommand
|
|
*
|
|
* Summary: Execute a menu command for our main form
|
|
*
|
|
* Parameters:
|
|
* command IN menu command to execute
|
|
*
|
|
* Returns:
|
|
* true if event was handled
|
|
*
|
|
* Called By:
|
|
* MainFrmEventHandler()
|
|
*
|
|
* Notes:
|
|
*
|
|
* History:
|
|
* 18-apr-2000 dia Ceated
|
|
*
|
|
****************************************************************/
|
|
static Boolean
|
|
MainFrmDoCommand (UInt16 command)
|
|
{
|
|
Boolean handled = false;
|
|
|
|
UInt16 cardNo;
|
|
LocalID dbID;
|
|
DmSearchStateType searchState;
|
|
|
|
DmGetNextDatabaseByTypeCreator(true, &searchState, sysFileTApplication,
|
|
HelperReceiverCreator, true, &cardNo, &dbID);
|
|
|
|
switch (command)
|
|
{
|
|
case MainOptionsAbout:
|
|
MenuEraseStatus(0);
|
|
HsAboutHandspringApp(cardNo, dbID, "2007", "Palm DTS Team");
|
|
handled = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return handled;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************
|
|
* Function: MainFrmHandleControl
|
|
*
|
|
* Summary: Handle a control select event
|
|
*
|
|
* Parameters:
|
|
* eventP IN The control select event...
|
|
*
|
|
* Returns:
|
|
* true if event was handled
|
|
*
|
|
* Called By:
|
|
* MainFrmEventHandler()
|
|
*
|
|
* Notes:
|
|
*
|
|
* History:
|
|
* 18-apr-2000 dia Ceated
|
|
*
|
|
****************************************************************/
|
|
static Boolean
|
|
MainFrmHandleControl (EventPtr eventP)
|
|
{
|
|
Boolean handled = false;
|
|
|
|
// Figure out which of the two buttons it was...
|
|
switch (eventP->data.ctlSelect.controlID)
|
|
{
|
|
case rscMainViewEnableButtonID:
|
|
DoRegister();
|
|
handled = true;
|
|
break;
|
|
|
|
case rscMainViewDisableButtonID:
|
|
DoUnregister();
|
|
handled = true;
|
|
break;
|
|
|
|
default:
|
|
// allow other events to be handled by frmhandleevent
|
|
handled = false;
|
|
break;
|
|
|
|
}
|
|
|
|
return handled;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************
|
|
* Function: MainFrmEventHandler
|
|
*
|
|
* Summary: Event handler for our main form.
|
|
*
|
|
* Parameters:
|
|
* eventP IN pointer to event to handle
|
|
*
|
|
* Returns:
|
|
* true if event was handled
|
|
*
|
|
* Called By:
|
|
* FrmDispatchEvent() when event is for our main form.
|
|
* FrmDispatchEvent() is called by our AppEventLoop()
|
|
*
|
|
* Notes:
|
|
*
|
|
* History:
|
|
* 18-apr-2000 dia Ceated
|
|
*
|
|
****************************************************************/
|
|
static Boolean
|
|
MainFrmEventHandler (EventPtr eventP)
|
|
{
|
|
FormPtr formP;
|
|
Boolean handled = false;
|
|
|
|
switch (eventP->eType)
|
|
{
|
|
// -------------------------------------------------------
|
|
// Init the form
|
|
// -------------------------------------------------------
|
|
case frmOpenEvent:
|
|
formP = FrmGetActiveForm ();
|
|
MainFrmInit (formP);
|
|
FrmDrawForm (formP);
|
|
FrmNavObjectTakeFocus(formP, rscMainViewEnableButtonID);
|
|
handled = true;
|
|
|
|
break;
|
|
|
|
// -------------------------------------------------------
|
|
// Menu commands
|
|
// -------------------------------------------------------
|
|
case menuEvent:
|
|
handled = MainFrmDoCommand (eventP->data.menu.itemID);
|
|
break;
|
|
|
|
|
|
|
|
// -------------------------------------------------------
|
|
// Buttons
|
|
// -------------------------------------------------------
|
|
case ctlSelectEvent:
|
|
handled = MainFrmHandleControl (eventP);
|
|
break;
|
|
|
|
|
|
|
|
// -------------------------------------------------------
|
|
// Close our form
|
|
// -------------------------------------------------------
|
|
case frmCloseEvent:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return handled;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************
|
|
* Function: AppStart
|
|
*
|
|
* Summary: Application initialization when being launched
|
|
* as a normal application (i.e. not to execute an action code).
|
|
*
|
|
* Parameters:
|
|
* void
|
|
*
|
|
* Returns:
|
|
* 0 if no error
|
|
*
|
|
* Called By:
|
|
* PilotMain when action code is for a normal launch.
|
|
*
|
|
* Notes:
|
|
*
|
|
* History:
|
|
* 26-Feb-1999 RM Ceated
|
|
*
|
|
****************************************************************/
|
|
|
|
static UInt32
|
|
AppStart(void)
|
|
{
|
|
FrmGotoForm (rscMainViewFormID);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***************************************************************
|
|
* Function: AppStop
|
|
*
|
|
* Summary: Application cleanup. This routine cleans up
|
|
* all initialization performed by AppStart().
|
|
*
|
|
* Parameters:
|
|
* void
|
|
*
|
|
* Returns:
|
|
* 0 if no error
|
|
*
|
|
* Called By:
|
|
* PilotMain, after EventLoop returns
|
|
*
|
|
* Notes:
|
|
*
|
|
* History:
|
|
* 26-Feb-1999 RM Ceated
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
AppStop (void)
|
|
{
|
|
FrmCloseAllForms();
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************
|
|
* Function: AppEventLoop
|
|
*
|
|
* Summary: This routine loads form resources and set the event
|
|
* handler for the form loaded.
|
|
*
|
|
* Parameters:
|
|
* eventP IN pointer to event
|
|
*
|
|
* Returns:
|
|
* true if event was handled.
|
|
*
|
|
* Called By:
|
|
* AppEventLoop.
|
|
*
|
|
* Notes:
|
|
*
|
|
* History:
|
|
* 26-Feb-1999 RM Ceated
|
|
*
|
|
****************************************************************/
|
|
static Boolean
|
|
AppHandleEvent (EventPtr eventP)
|
|
{
|
|
UInt16 formID;
|
|
FormPtr frmP;
|
|
Boolean handled = false;
|
|
|
|
if (eventP->eType == frmLoadEvent)
|
|
{
|
|
// Load the form resource.
|
|
formID = eventP->data.frmLoad.formID;
|
|
frmP = FrmInitForm (formID);
|
|
FrmSetActiveForm (frmP);
|
|
|
|
// Set the event handler for the form. The handler of the currently
|
|
// active form is called by FrmHandleEvent each time is receives an
|
|
// event.
|
|
switch (formID)
|
|
{
|
|
case rscMainViewFormID:
|
|
FrmSetEventHandler(frmP, MainFrmEventHandler);
|
|
handled = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return handled;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************
|
|
* Function: AppEventLoop
|
|
*
|
|
* Summary: Main event loop for the application
|
|
*
|
|
* Parameters:
|
|
* void
|
|
*
|
|
* Returns:
|
|
* 0 if no error
|
|
*
|
|
* Called By:
|
|
* PilotMain after initializing.
|
|
*
|
|
* Notes:
|
|
*
|
|
* History:
|
|
* 26-Feb-1999 RM Ceated
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
AppEventLoop(void)
|
|
{
|
|
UInt16 err;
|
|
EventType event;
|
|
|
|
do
|
|
{
|
|
EvtGetEvent (&event, evtWaitForever);
|
|
|
|
if (!SysHandleEvent (&event))
|
|
if (!MenuHandleEvent (0, &event, &err))
|
|
if (!AppHandleEvent (&event))
|
|
FrmDispatchEvent (&event);
|
|
|
|
} while(event.eType != appStopEvent);
|
|
}
|
|
|
|
|
|
|
|
// Executes the helperNotifyActionCodeExecute request if it is intended
|
|
// for this helper
|
|
static Boolean
|
|
ProcessExecute (HelperNotifyEventType* helperParamP)
|
|
{
|
|
HelperNotifyExecuteType* executeP;
|
|
Boolean handled = false;
|
|
|
|
executeP = helperParamP->data.executeP;
|
|
|
|
// If this is a request for SMS service and it either targets
|
|
// this specific helper via its helperID or wildcard (0), then
|
|
// handle it.
|
|
|
|
if ( (executeP->serviceClassID == kHelperServiceClassIDSMS)
|
|
&&
|
|
((executeP->helperAppID == prvMyHelperID) || (executeP->helperAppID == 0)) )
|
|
{
|
|
UInt32 buttonNo;
|
|
HelperServiceSMSDetailsType * detailsP = executeP->detailsP;
|
|
|
|
buttonNo = FrmCustomAlert(rscHelperReceiverSMSAlertID, "Send SMS", executeP->displayedName, executeP->dataP);
|
|
if (buttonNo)
|
|
{
|
|
if (detailsP && detailsP->message && StrLen(detailsP->message))
|
|
{
|
|
FrmCustomAlert(rscHelperReceiverMessageAlertID, NULL, NULL, detailsP->message);
|
|
}
|
|
else
|
|
{
|
|
FrmCustomAlert(rscHelperReceiverMessageAlertID, NULL, NULL, "(empty message)");
|
|
}
|
|
}
|
|
|
|
executeP->err = 0;
|
|
handled = true;
|
|
}
|
|
else if ( (executeP->serviceClassID == kHelperServiceClassIDEMail)
|
|
&&
|
|
((executeP->helperAppID == prvMyHelperID) || (executeP->helperAppID == 0)) )
|
|
{
|
|
UInt32 buttonNo;
|
|
HelperServiceEMailDetailsType* detailsP = executeP->detailsP;
|
|
|
|
buttonNo = FrmCustomAlert(rscHelperReceiverEmailAlertID, "Send Email", executeP->displayedName, executeP->dataP);
|
|
if (buttonNo)
|
|
{
|
|
if (detailsP && detailsP->message && StrLen(detailsP->message))
|
|
{
|
|
FrmCustomAlert(rscHelperReceiverMessageAlertID, "Subject: ", detailsP->subject, detailsP->message);
|
|
}
|
|
else
|
|
{
|
|
FrmCustomAlert(rscHelperReceiverMessageAlertID, NULL, NULL, "(empty message)");
|
|
}
|
|
}
|
|
|
|
executeP->err = 0;
|
|
handled = true;
|
|
}
|
|
else if ( (executeP->serviceClassID == kHelperServiceClassIDURL)
|
|
&&
|
|
((executeP->helperAppID == prvMyHelperID) || (executeP->helperAppID == 0)) )
|
|
{
|
|
UInt32 buttonNo;
|
|
|
|
buttonNo = FrmCustomAlert(rscHelperReceiverWebAlertID, "Go To Link", executeP->dataP, NULL);
|
|
|
|
executeP->err = 0;
|
|
handled = true;
|
|
}
|
|
|
|
return (handled);
|
|
} // ProcessExecute
|
|
|
|
|
|
|
|
// Executes the helperNotifyActionCodeValidate request if it is intended
|
|
// for this helper; the purpose of this request is to determine whether
|
|
// any helper (or a specific helper) for a specific service class exists,
|
|
// without incurring the memory management overhead of
|
|
// helperNotifyActionCodeEnumerate.
|
|
static Boolean
|
|
ProcessValidate (HelperNotifyEventType* helperParamP)
|
|
{
|
|
HelperNotifyValidateType* validateP;
|
|
Boolean handled = false;
|
|
|
|
validateP = helperParamP->data.validateP;
|
|
|
|
// If this is a request for Voice or Fax service and it either targets
|
|
// this specific helper via its helperID or wildcard (0), then
|
|
// handle it.
|
|
if ( ((validateP->serviceClassID == kHelperServiceClassIDSMS)
|
|
||(validateP->serviceClassID == kHelperServiceClassIDEMail)
|
|
||(validateP->serviceClassID == kHelperServiceClassIDURL))
|
|
&& (validateP->helperAppID == prvMyHelperID || validateP->helperAppID == 0) )
|
|
{
|
|
handled = true;
|
|
}
|
|
|
|
return (handled);
|
|
|
|
} // ProcessValidate
|
|
|
|
|
|
// Executes the helperNotifyActionCodeEnumerate request; the "host" makes
|
|
// this request in order to discover which services are available. All
|
|
// helpers are required to handle this call
|
|
static void
|
|
ProcessEnumerate (HelperNotifyEventType* helperParamP, UInt32 classID)
|
|
{
|
|
HelperNotifyEnumerateListType* nodeP;
|
|
|
|
// Allocate the enumeration list node
|
|
nodeP = MemPtrNew (sizeof(*nodeP));
|
|
if (!nodeP)
|
|
{
|
|
ErrNonFatalDisplay ("Out of memory");
|
|
return;
|
|
}
|
|
|
|
// Change owner to "system" so the memory will not be deleted automatically
|
|
// when we return from PilotMain
|
|
MemPtrSetOwner (nodeP, 0);
|
|
|
|
// Initialize the node
|
|
MemSet (nodeP, sizeof (*nodeP), 0);
|
|
|
|
// DOLATER; should get names from resources for localization.
|
|
|
|
// For display in default helper configuration and other UI
|
|
StrNCopy (nodeP->helperAppName, "Helper Receiver", sizeof(nodeP->helperAppName));
|
|
|
|
// For possible display in an action pop-up or similar UI gadget;
|
|
// it's a good idea to keep this short.
|
|
StrNCopy (nodeP->actionName, "Send Message", sizeof(nodeP->actionName));
|
|
|
|
nodeP->helperAppID = prvMyHelperID; // our unique helper ID
|
|
|
|
nodeP->serviceClassID = classID; // class of service we support
|
|
|
|
// Finally, link in the node into the list
|
|
HelperEnumerateEnqueueEntry ((HelperNotifyEnumerateListType*)helperParamP->data.enumerateP, nodeP); // HelperEnumNodeEnqueue is a macro
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/***************************************************************
|
|
* Function: PilotMain
|
|
*
|
|
* Summary: Entry point
|
|
*
|
|
* Parameters:
|
|
* cmd IN Action code for the app. This is one of the
|
|
* action codes sysAppLaunchCmdXXX defined in
|
|
* <SystemMgr.h>
|
|
* cmdPBP IN Parameter block pointer for action code.
|
|
* launchFlags IN Launch flags, one or more of
|
|
* sysAppLaunchFlagXXX defined in <SystemMgr.h>
|
|
*
|
|
* Returns:
|
|
* 0 if no error
|
|
*
|
|
* Called By:
|
|
* PalmOS when launching the app or asking it to execute an
|
|
* action code like find or goto.
|
|
*
|
|
* Notes:
|
|
*
|
|
*
|
|
* History:
|
|
* 26-Feb-1999 RM Ceated by Ron Marianetti
|
|
* 24-May-2000 vmk Modified for the "semi-final" Helpers API
|
|
*
|
|
****************************************************************/
|
|
static UInt32
|
|
HelperReceiverPilotMain (UInt16 cmd, void* cmdPBP, UInt16 launchFlags)
|
|
{
|
|
UInt32 err;
|
|
|
|
switch (cmd)
|
|
{
|
|
case sysAppLaunchCmdNormalLaunch:
|
|
{
|
|
err = AppStart(); // Application start code
|
|
if (err) return err;
|
|
|
|
AppEventLoop(); // Event loop
|
|
|
|
AppStop (); // Application stop code
|
|
}
|
|
break;
|
|
case sysAppLaunchCmdNotify:
|
|
{
|
|
SysNotifyParamType* paramP = (SysNotifyParamType*) cmdPBP;
|
|
|
|
// Look for notifications from the helper manager...
|
|
if (paramP->notifyType == sysNotifyHelperEvent)
|
|
{
|
|
HelperNotifyEventType* helperParamP = (HelperNotifyEventType*) paramP->notifyDetailsP;
|
|
|
|
// Just to verify that nothing broke...
|
|
#if (kHelperNotifyCurrentVersion != 1)
|
|
#error "Helper structure changed--are we still OK?"
|
|
#endif
|
|
|
|
// Figure out which type of helper manager event...
|
|
if (helperParamP->actionCode == kHelperNotifyActionCodeExecute)
|
|
{
|
|
// Only one helper is allowed to actually handle this request
|
|
if (!paramP->handled)
|
|
{
|
|
paramP->handled = ProcessExecute (helperParamP);
|
|
// Must be careful not to set paramP->handled to false because
|
|
// others may have already handled this notification
|
|
}
|
|
}
|
|
|
|
else if (helperParamP->actionCode == kHelperNotifyActionCodeValidate)
|
|
{
|
|
// Only one helper is allowed to actually handle this request
|
|
if (!paramP->handled)
|
|
{
|
|
paramP->handled = ProcessValidate (helperParamP);
|
|
}
|
|
}
|
|
|
|
else if (helperParamP->actionCode == kHelperNotifyActionCodeEnumerate)
|
|
{
|
|
// More than one helper may need to handle this request,
|
|
// so we don't check the "handled" flag here
|
|
|
|
ProcessEnumerate (helperParamP, kHelperServiceClassIDSMS);
|
|
ProcessEnumerate (helperParamP, kHelperServiceClassIDEMail);
|
|
ProcessEnumerate (helperParamP, kHelperServiceClassIDURL);
|
|
|
|
paramP->handled = true; // all helpers are required to handle
|
|
// the "Enumerate" request.
|
|
}
|
|
|
|
else
|
|
{
|
|
ErrNonFatalDisplay ("unknown helperNotifyActionCode");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case sysAppLaunchCmdSyncNotify:
|
|
case sysAppLaunchCmdSystemReset:
|
|
// Want to register upon reset and upon card insertion...
|
|
// ...need to set "-resetAfterInstall" to get these notification from a card.
|
|
DoRegister();
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Make a call to a more specific functiom
|
|
|
|
UInt32
|
|
PilotMain (UInt16 cmd, void* cmdPBP, UInt16 launchFlags)
|
|
{
|
|
return HelperReceiverPilotMain (cmd, cmdPBP, launchFlags);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|