996 lines
24 KiB
C
996 lines
24 KiB
C
/**
|
|
* \file SimpleSMS.c
|
|
*
|
|
* SimpleSMS
|
|
*
|
|
* This is the main source file for the Simple SMS App. This
|
|
* code demonstrates how to write your own SMS application. The app
|
|
* will register with the Phone Library, send a custom message, and
|
|
* display a dialog for incoming messages.
|
|
*
|
|
* \license
|
|
*
|
|
* Copyright (c) 2002 Handspring Inc., All Rights Reserved
|
|
*
|
|
* $Id:$
|
|
*
|
|
***************************************************************/
|
|
#include <PalmOS.h>
|
|
#include <HsNav.h>
|
|
#include <HsExt.h>
|
|
#include <HsPhone.h>
|
|
|
|
#include "SimpleSMS.h"
|
|
|
|
// -------------------------------------------------------------
|
|
// Constants
|
|
// -------------------------------------------------------------
|
|
#define appFileCreator 'HSMS'
|
|
#define appVersionNum 0x01
|
|
#define appPrefID 0x00
|
|
#define appPrefVersionNum 0x01
|
|
#define kMinVersionSupported 0x3523040
|
|
// -------------------------------------------------------------
|
|
// Structures
|
|
// -------------------------------------------------------------
|
|
#define serviceCenterSize 40
|
|
#define addressSize 40
|
|
#define messageSize 160
|
|
|
|
typedef struct
|
|
{
|
|
char address[addressSize + 1];
|
|
char message[messageSize + 1];
|
|
} SimpleSMSPreferenceType;
|
|
|
|
typedef struct NBSNotificationEventType PhnNBSNotificationEventType;
|
|
// -------------------------------------------------------------
|
|
// Globals
|
|
// -------------------------------------------------------------
|
|
static SimpleSMSPreferenceType smsPrefs;
|
|
static Boolean smsLibLoaded;
|
|
static UInt16 smsLibRef;
|
|
|
|
// -------------------------------------------------------------
|
|
// Prototypes
|
|
// -------------------------------------------------------------
|
|
static Err StartApplication (void);
|
|
static void EventLoop (void);
|
|
static void StopApplication (void);
|
|
static Boolean SimpleSMSEvent (EventPtr event);
|
|
|
|
static UInt32 HandlePhoneLibraryEvent (MemPtr cmdPBP, UInt16 launchFlags);
|
|
static Err LoadPhoneLibrary (UInt16* libRefP, Boolean* libLoadedP);
|
|
static Err SMSRegister (Boolean bReg);
|
|
static void SendTheMessage (void);
|
|
static void DisplayMessage (UInt32 messageID);
|
|
static void TurnOnOptionLock (void);
|
|
static void* GetObjectPtr (UInt16 objectID);
|
|
static void CopyFromGlobalToFields (void);
|
|
static UInt32 CopyFromFieldsToGlobal (void);
|
|
|
|
static void HandleNotificationEvent ( MemPtr cmdPBP, UInt16 launchFlags);
|
|
|
|
// -------------------------------------------------------------
|
|
// Functions
|
|
// -------------------------------------------------------------
|
|
|
|
/****************************************************************/
|
|
/* PilotMain */
|
|
/**
|
|
* Main entry point
|
|
*
|
|
* \param cmd IN Value specifying the launch code.
|
|
* \param cmdPBP IN Pointer to a structure that is associated with the launch code.
|
|
* \param launchFlags IN Value providing extra information about the launch.
|
|
*
|
|
* \retval UInt32
|
|
*
|
|
****************************************************************/
|
|
UInt32
|
|
PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
|
|
{
|
|
UInt32 error;
|
|
|
|
switch (cmd)
|
|
{
|
|
case sysAppLaunchCmdNormalLaunch:
|
|
// normal application launch
|
|
error = StartApplication ();
|
|
if (error)
|
|
return error;
|
|
|
|
EventLoop ();
|
|
|
|
StopApplication ();
|
|
break;
|
|
|
|
case phnLibLaunchCmdRegister:
|
|
// Received when device is reset (or the library is loaded ?)
|
|
// DbgBreak();
|
|
// SMSRegister (true);
|
|
break;
|
|
|
|
case 0x7000: // For Treo 300 workaround. Currently the launch code is different on Treo 300 than 180/270
|
|
case phnLibLaunchCmdEvent:
|
|
// we have an event from the Phone library, so handle it
|
|
error = HandlePhoneLibraryEvent (cmdPBP, launchFlags);
|
|
if (error)
|
|
return error;
|
|
break;
|
|
|
|
case sysAppLaunchCmdNotify:
|
|
HandleNotificationEvent (cmdPBP, launchFlags);
|
|
break;
|
|
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return errNone;
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* StartApplication */
|
|
/**
|
|
* Application start
|
|
*
|
|
* \retval Err
|
|
*
|
|
****************************************************************/
|
|
static Err
|
|
StartApplication (void)
|
|
{
|
|
Err error = 0;
|
|
char errMsg[10];
|
|
|
|
smsLibLoaded = false;
|
|
smsLibRef = 0;
|
|
|
|
|
|
#if 0 // This block is not really neccessary since we use the Handspring/Treo's phone libraries
|
|
// whick guarantees the device is (should be) a Treo.
|
|
|
|
UInt16 prefsSize;
|
|
void* procP;
|
|
UInt32 value;
|
|
|
|
// Make sure that we are running on the Treo
|
|
// Make sure that we are at the appropriate Palm OS version
|
|
if (!FtrGet (hsFtrCreator, hsFtrIDVersion, &value))
|
|
{
|
|
if (value < kMinVersionSupported)
|
|
{
|
|
FrmCustomAlert (resAlertPhoneLibrary, "PalmOS version too low", errMsg, NULL);
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FrmCustomAlert (resAlertPhoneLibrary, "No hsFtrIDVersion", errMsg, NULL);
|
|
return 1;
|
|
}
|
|
|
|
// Make sure that we support the HsIndicator function call.
|
|
// We use this test to make sure that we are on a Treo device.
|
|
procP = HsGetTrapAddress (hsSelIndicator);
|
|
if (procP && procP != HsGetTrapAddress(hsSelUnimplemented))
|
|
{
|
|
// Read the saved preferences / saved-state information.
|
|
prefsSize = sizeof(SimpleSMSPreferenceType);
|
|
if (PrefGetAppPreferences (appFileCreator, appPrefID, &smsPrefs, &prefsSize, true) != noPreferenceFound)
|
|
;
|
|
}
|
|
else
|
|
{
|
|
// Display the error dialog and return with error
|
|
FrmCustomAlert (resAlertPhoneLibrary, "No hsSelIndicator proc", errMsg, NULL);
|
|
return 1;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
// load the Phone Library
|
|
error = LoadPhoneLibrary (&smsLibRef, &smsLibLoaded);
|
|
if (error)
|
|
{
|
|
StrIToA(errMsg, error);
|
|
FrmCustomAlert (resAlertPhoneLibrary, "Can't Load the Phone Library", errMsg, NULL);
|
|
return 1;
|
|
}
|
|
else
|
|
{ // We were able to load the library
|
|
// Now, let's register with the SMS library
|
|
error = SMSRegister (true);
|
|
if (error)
|
|
FrmAlert (resAlertCantRegisterWithSMSLibrary);
|
|
}
|
|
|
|
// verify the Phone is powered and SIM status is ready
|
|
if ( PhnLibModulePowered (smsLibRef) == false)
|
|
{
|
|
FrmAlert (resAlertPhoneNotReady);
|
|
if (smsLibLoaded)
|
|
(void)PhnLibClose (smsLibRef);
|
|
return 1;
|
|
}
|
|
|
|
// Check what device we are on: GSM or CDMA
|
|
|
|
FrmGotoForm(resFormIDSimpleSMS);
|
|
|
|
/*
|
|
(void)HsAttrGet (hsAttrPhoneType, 0, &phoneType);
|
|
if (phoneType == hsAttrPhoneTypeGSM)
|
|
{
|
|
FrmGotoForm (resFormIDSimpleSMS);
|
|
}
|
|
else if (phoneType == hsAttrPhoneTypeCDMA)
|
|
{
|
|
FrmGotoForm (resFormIDSimpleSMSNoSend);
|
|
}
|
|
else
|
|
{
|
|
// Default to the GSM (send/receive message) form. Pre-Treo 300 devices do not support this attribute.
|
|
FrmGotoForm (resFormIDSimpleSMS);
|
|
phoneType = hsAttrPhoneTypeGSM;
|
|
}
|
|
*/
|
|
|
|
return error;
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* EventLoop */
|
|
/**
|
|
* Main event loop
|
|
*
|
|
* \retval none
|
|
*
|
|
****************************************************************/
|
|
static void EventLoop(void)
|
|
{
|
|
UInt16 err;
|
|
UInt16 formID;
|
|
FormPtr formP;
|
|
EventType event;
|
|
|
|
do
|
|
{
|
|
EvtGetEvent (&event, sysTicksPerSecond/2);
|
|
|
|
if (SysHandleEvent (&event))
|
|
continue;
|
|
if (MenuHandleEvent ((void *)0, &event, &err))
|
|
continue;
|
|
if (event.eType == frmLoadEvent)
|
|
{
|
|
formID = event.data.frmLoad.formID;
|
|
formP = FrmInitForm (formID);
|
|
FrmSetActiveForm (formP);
|
|
|
|
switch (formID)
|
|
{
|
|
case resFormIDSimpleSMS:
|
|
FrmSetEventHandler (formP, (FormEventHandlerPtr)SimpleSMSEvent);
|
|
break;
|
|
case resFormIDSimpleSMSNoSend:
|
|
FrmSetEventHandler (formP, (FormEventHandlerPtr)SimpleSMSEvent);
|
|
break;
|
|
}
|
|
}
|
|
|
|
FrmDispatchEvent(&event);
|
|
|
|
} while (event.eType != appStopEvent);
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* StopApplication */
|
|
/**
|
|
* Stop the application
|
|
*
|
|
* \retval none
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
StopApplication (void)
|
|
{
|
|
//if (phoneType == hsAttrPhoneTypeGSM)
|
|
//{
|
|
// CopyFromFieldsToGlobal();
|
|
//}
|
|
|
|
// Write the saved preferences / saved-state information. This data
|
|
// will be backed up during a HotSync.
|
|
//PrefSetAppPreferences (appFileCreator, appPrefID, appPrefVersionNum, &smsPrefs, sizeof (smsPrefs), true);
|
|
|
|
// Close all the open forms.
|
|
FrmCloseAllForms ();
|
|
|
|
// Release the SMS library
|
|
if (smsLibLoaded)
|
|
PhnLibClose(smsLibRef);
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* SimpleSMSEvent */
|
|
/**
|
|
* Event handler for the main form
|
|
*
|
|
* \param event IN Event to process
|
|
*
|
|
* \retval Boolean
|
|
*
|
|
****************************************************************/
|
|
static Boolean
|
|
SimpleSMSEvent (EventPtr eventP)
|
|
{
|
|
UInt16 err;
|
|
UInt16 cardNo;
|
|
FormPtr frmP;
|
|
LocalID dbID;
|
|
FieldPtr fieldP;
|
|
DmSearchStateType searchState;
|
|
Boolean handled = false;
|
|
|
|
DmGetNextDatabaseByTypeCreator(true, &searchState, sysFileTApplication,
|
|
appFileCreator, true, &cardNo, &dbID);
|
|
|
|
switch (eventP->eType)
|
|
{
|
|
case menuEvent:
|
|
switch (eventP->data.menu.itemID)
|
|
{
|
|
case resMenuItemAbout:
|
|
MenuEraseStatus (0);
|
|
HsAboutHandspringApp (cardNo, dbID, "2007", "palmOne DTS Team");
|
|
handled = true;
|
|
break;
|
|
|
|
case resMenuItemUnRegister:
|
|
MenuEraseStatus (0);
|
|
err = SMSRegister (false);
|
|
if (err)
|
|
FrmAlert (resAlertCantRegisterWithSMSLibrary);
|
|
handled = true;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case frmOpenEvent:
|
|
frmP = FrmGetActiveForm();
|
|
|
|
// Set the focus to the edit field
|
|
FrmSetFocus(frmP, noFocus);
|
|
FrmSetFocus(frmP, FrmGetObjectIndex(frmP, resButtonSend));
|
|
FrmDrawForm (frmP);
|
|
|
|
if (FrmGetActiveFormID () == resFormIDSimpleSMS)
|
|
{
|
|
CopyFromGlobalToFields();
|
|
|
|
|
|
|
|
TurnOnOptionLock ();
|
|
}
|
|
else if (FrmGetActiveFormID () == resFormIDSimpleSMSNoSend)
|
|
{
|
|
}
|
|
|
|
// Setup the battery and signal gadgets
|
|
{
|
|
UInt32 hsStatusVersion;
|
|
|
|
if (FtrGet (hsFtrCreator, hsFtrIDStatusGadgetRev, &hsStatusVersion) == 0)
|
|
{
|
|
HsStatusSetGadgetType (frmP, resGadgetMainBatteryLevel, hsStatusGadgetBattery);
|
|
HsStatusSetGadgetType (frmP, resGadgetSignalLevel, hsStatusGadgetSignal);
|
|
}
|
|
}
|
|
|
|
handled = true;
|
|
break;
|
|
|
|
case ctlSelectEvent:
|
|
switch (eventP->data.ctlSelect.controlID)
|
|
{
|
|
case resButtonSend:
|
|
SendTheMessage();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case fldEnterEvent:
|
|
fieldP = (FieldType*)GetObjectPtr (eventP->data.fldEnter.fieldID);
|
|
switch (eventP->data.fldEnter.fieldID)
|
|
{
|
|
case resFieldAddress:
|
|
case resFieldServiceCenter:
|
|
FldHandleEvent (fieldP, eventP);
|
|
TurnOnOptionLock ();
|
|
handled = true;
|
|
break;
|
|
|
|
case resFieldMessage:
|
|
FldHandleEvent (fieldP, eventP);
|
|
if (FldGetInsPtPosition(fieldP) == 0)
|
|
HsGrfSetStateExt(false, false, false, true, false, true);
|
|
handled = true;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return handled;
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* HandleNotificationEvent */
|
|
/**
|
|
* This function handles all Phone specific events.
|
|
*
|
|
* \param cmdPBP IN Pointer to a structure that is associated with the launch code.
|
|
* \param launchFlags IN Value providing extra information about the launch.
|
|
*
|
|
* \retval UInt32 - Result of launch
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
HandleNotificationEvent ( MemPtr cmdPBP, UInt16 launchFlags)
|
|
{
|
|
SysNotifyParamType* notifyParam = (SysNotifyParamType*)cmdPBP ;
|
|
|
|
launchFlags = launchFlags; // Prevent compiler error
|
|
|
|
if (notifyParam->notifyType == phnNBSEvent)
|
|
{
|
|
PhnNBSNotificationEventType* NBSParamP = (PhnNBSNotificationEventType*) notifyParam->notifyDetailsP;
|
|
|
|
|
|
// Display NBS info
|
|
|
|
if (NBSParamP->binary) // NBS binary
|
|
{
|
|
;
|
|
}
|
|
else // NBS text
|
|
{
|
|
|
|
char dstPort[20], srcPort[20];
|
|
|
|
// NBSParamP->refnum;
|
|
// NBSParamP->maxnum;
|
|
// NBSParamP->seqnum;
|
|
|
|
// NBSParamP->srcPort;
|
|
// NBSParamP->dstPort;
|
|
|
|
// NBSParamP->senderP;
|
|
// NBSParamP->datetime;
|
|
|
|
StrIToA(dstPort, (long) NBSParamP->dstPort);
|
|
StrIToA(srcPort, (long) NBSParamP->srcPort);
|
|
StrCat(dstPort, "/");
|
|
StrCat(dstPort, srcPort);
|
|
FrmCustomAlert(resAlertIncomingNBSMessage, NBSParamP->senderP, dstPort, NBSParamP->dataP);
|
|
|
|
|
|
//Display like regular SMS.
|
|
//DisplayMessage(NBSParamP->msgID);
|
|
|
|
}
|
|
|
|
|
|
notifyParam->handled = true;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************/
|
|
/* HandlePhoneLibraryEvent */
|
|
/**
|
|
* This function handles all Phone specific events.
|
|
*
|
|
* \param cmdPBP IN Pointer to a structure that is associated with the launch code.
|
|
* \param launchFlags IN Value providing extra information about the launch.
|
|
*
|
|
* \retval UInt32 - Result of launch
|
|
*
|
|
****************************************************************/
|
|
static UInt32
|
|
HandlePhoneLibraryEvent(MemPtr cmdPBP, UInt16 launchFlags)
|
|
{
|
|
PhnEventPtr eventP = (PhnEventPtr)cmdPBP;
|
|
UInt32 flags;
|
|
Err error = 0;
|
|
UInt32 locked = 0;
|
|
|
|
launchFlags = launchFlags; // Prevent compiler warning of unused var
|
|
|
|
switch (eventP->eventType)
|
|
{
|
|
case phnEvtSegmentInd:
|
|
case phnEvtMessageInd:
|
|
// a message has been received
|
|
DisplayMessage (eventP->data.params.id);
|
|
// Tell the Phone Library that we handled the event and no
|
|
// other app needs to know about this.
|
|
eventP->acknowledge = true;
|
|
|
|
HsAttrGet(hsAttrKeyboardLocked, 0, &locked);
|
|
|
|
if (locked)
|
|
HsAttrSet(hsAttrKeyboardLocked, 0, 0);
|
|
|
|
break;
|
|
|
|
case phnEvtMessageStat:
|
|
// a message status has changed
|
|
switch (eventP->data.params.newStatus)
|
|
{
|
|
case kSending:
|
|
// this is an expected status, do nothing
|
|
break;
|
|
case kSent:
|
|
// ok, did we successfully send the message?
|
|
error = PhnLibGetFlags (smsLibRef, eventP->data.params.id, &flags);
|
|
if (error)
|
|
return error;
|
|
if ((flags & kFailed) == 0)
|
|
FrmAlert (resAlertSuccessfulTransfer);
|
|
else
|
|
FrmAlert (resAlertUnsuccessfulTransfer);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
eventP->acknowledge = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* LoadPhoneLibrary */
|
|
/**
|
|
* Get a libRef to the Phone library
|
|
*
|
|
* \param libRefP OUT Pointer to library reference ID to return. If NULL,
|
|
* library isn't loaded and an error is returned.
|
|
* \param libLoadedP INOUT Pointer to boolean indicating whether the library
|
|
* had to be loaded or not. If the value is true on
|
|
* entry, it will be left as true, even if the library
|
|
* was found already loaded - this allows reuse of the
|
|
* same boolean indicating load status throughout the
|
|
* application. This routine NEVER sets this parameter
|
|
* to false.
|
|
*
|
|
* \retval none
|
|
*
|
|
****************************************************************/
|
|
static Err
|
|
LoadPhoneLibrary(UInt16* libRefP, Boolean* libLoadedP)
|
|
{
|
|
Err error = 0;
|
|
|
|
error = HsGetPhoneLibrary(libRefP);
|
|
if (error) return error;
|
|
|
|
error = PhnLibOpen(*libRefP);
|
|
if (error) return error;
|
|
|
|
*libLoadedP = true;
|
|
|
|
return error;
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* SMSRegister */
|
|
/**
|
|
* This routine registers this application with the SMS library.
|
|
*
|
|
* \param bReg IN true to register; false to unregister
|
|
*
|
|
* \retval none
|
|
*
|
|
****************************************************************/
|
|
static Err
|
|
SMSRegister (Boolean bReg)
|
|
{
|
|
Boolean libLoaded = smsLibLoaded;
|
|
Err error = 0;
|
|
UInt16 libRef = smsLibRef;
|
|
|
|
if (!libLoaded)
|
|
error = LoadPhoneLibrary (&libRef, &libLoaded);
|
|
|
|
if (!error)
|
|
{
|
|
// Register this application with the Phone library so it will receive the appropriate events
|
|
error = PhnLibRegister (libRef, appFileCreator, bReg ? phnServiceSMS : 0);
|
|
if (libLoaded)
|
|
(void)PhnLibClose (libRef);
|
|
}
|
|
|
|
|
|
// Register NBS Notification
|
|
{
|
|
UInt16 cardNo;
|
|
LocalID dbID;
|
|
DmSearchStateType searchState;
|
|
|
|
DmGetNextDatabaseByTypeCreator(true, &searchState, sysFileTApplication,
|
|
appFileCreator, true, &cardNo, &dbID);
|
|
|
|
if ( bReg)
|
|
{
|
|
error = SysNotifyRegister (cardNo, dbID, phnNBSEvent, NULL, sysNotifyNormalPriority, NULL);
|
|
if (error == sysNotifyErrDuplicateEntry) // Already registered
|
|
error = 0; // This is OK. Clear this error
|
|
}
|
|
else
|
|
error = SysNotifyUnregister (cardNo, dbID, phnNBSEvent,sysNotifyNormalPriority);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* SendTheMessage */
|
|
/**
|
|
* This routine will send the message
|
|
*
|
|
* \retval none
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
SendTheMessage(void)
|
|
{
|
|
UInt32 msgID = 0;
|
|
PhnAddressList addList;
|
|
PhnAddressHandle addressH;
|
|
Err error = 0;
|
|
DmOpenRef smsRefNum = 0; // CDMA workaround
|
|
|
|
// verify the Phone is powered
|
|
if (!PhnLibModulePowered (smsLibRef))
|
|
{
|
|
FrmAlert (resAlertPhoneNotReady);
|
|
return;
|
|
}
|
|
|
|
// verify the Phone is on the network
|
|
if (!PhnLibRegistered (smsLibRef))
|
|
{
|
|
FrmAlert (resAlertNotRegistered);
|
|
return;
|
|
}
|
|
|
|
smsRefNum = PhnLibGetDBRef(smsLibRef); // CDMA workaround
|
|
|
|
// get the values from the fields into the globals
|
|
// check if there is no address input. if not, do not send SMS and return. Modified by TaoC
|
|
if (CopyFromFieldsToGlobal() == 1)
|
|
{
|
|
|
|
FrmAlert (resAlertNoAddressInput);
|
|
return ;
|
|
}
|
|
|
|
// now, create the new message
|
|
msgID = PhnLibNewMessage (smsLibRef, kMTOutgoing);
|
|
if (!msgID)
|
|
goto SendMessage_CloseAndRelease;
|
|
|
|
// the the owner of this new message to this application
|
|
PhnLibSetOwner (smsLibRef, msgID, appFileCreator);
|
|
|
|
// fill in the text of this message
|
|
PhnLibSetText (smsLibRef, msgID, smsPrefs.message, (short) StrLen(smsPrefs.message));
|
|
|
|
// fill in the address
|
|
addList = PhnLibNewAddressList (smsLibRef);
|
|
if (!addList)
|
|
goto SendMessage_CloseAndRelease;
|
|
|
|
addressH = PhnLibNewAddress (smsLibRef, smsPrefs.address, phnLibUnknownID);
|
|
if (!addressH)
|
|
goto SendMessage_CloseAndRelease;
|
|
|
|
PhnLibAddAddress (smsLibRef, addList, addressH);
|
|
MemHandleFree (addressH);
|
|
|
|
PhnLibSetAddresses (smsLibRef, msgID, addList);
|
|
// PhnLibDisposeAddressList (smsLibRef, addList);
|
|
|
|
// and fire the message off!
|
|
error = PhnLibSendMessage (smsLibRef, msgID, true);
|
|
|
|
SendMessage_CloseAndRelease:
|
|
PhnLibReleaseDBRef(smsLibRef, smsRefNum); // CDMA workaround
|
|
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* DisplayMessage */
|
|
/**
|
|
* This routine displays information about the given message
|
|
*
|
|
* \param messageID IN The message to display
|
|
*
|
|
* \retval none
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
DisplayMessage(UInt32 messageID)
|
|
{
|
|
PhnAddressList addList;
|
|
PhnAddressHandle addressH;
|
|
MemHandle messageH;
|
|
char* addressP;
|
|
char* messageP;
|
|
Err error = 0;
|
|
DmOpenRef smsRefNum = 0; // CDMA workaround
|
|
// we cannot use the global smsLibRef,
|
|
// because this can be called when the application is not running
|
|
UInt16 localSmsLibRef;
|
|
Boolean localSmsLibLoaded;
|
|
char errMsg[10];
|
|
UInt16 msgIndex;
|
|
|
|
//Initialize some values
|
|
localSmsLibLoaded = false;
|
|
localSmsLibRef = 0;
|
|
|
|
|
|
error = LoadPhoneLibrary (&localSmsLibRef, &localSmsLibLoaded);
|
|
if (error)
|
|
{
|
|
StrIToA(errMsg, error);
|
|
FrmCustomAlert (resAlertPhoneLibrary, "Can't Load the Phone Library", errMsg, NULL);
|
|
return;
|
|
}
|
|
|
|
smsRefNum = PhnLibGetDBRef(localSmsLibRef); // CDMA workaround
|
|
|
|
// get the address list
|
|
error = PhnLibGetAddresses (localSmsLibRef, messageID, &addList);
|
|
if (error)
|
|
goto DisplayMessage_CloseAndRelease;
|
|
|
|
// now get the first entry from the list
|
|
error = PhnLibGetNth (localSmsLibRef, addList, 1, &addressH);
|
|
if (error)
|
|
goto DisplayMessage_CloseAndRelease;
|
|
|
|
// now get the actual address
|
|
addressP = PhnLibGetField (localSmsLibRef, addressH, phnAddrFldPhone);
|
|
|
|
// and get the message text
|
|
error = PhnLibGetText (localSmsLibRef, messageID, &messageH);
|
|
if (error)
|
|
goto DisplayMessage_CloseAndRelease;
|
|
|
|
messageP = MemHandleLock (messageH);
|
|
|
|
// display the incoming message alert
|
|
FrmCustomAlert (resAlertIncomingMessage, addressP, messageP, NULL);
|
|
|
|
// and clean up
|
|
if (addressP)
|
|
MemPtrFree (addressP);
|
|
if (messageH)
|
|
{
|
|
MemHandleUnlock (messageH);
|
|
MemHandleFree (messageH);
|
|
}
|
|
|
|
if (!DmFindRecordByID(smsRefNum, messageID, &msgIndex))
|
|
{
|
|
DmRemoveRecord(smsRefNum, msgIndex); // CDMA workaround
|
|
}
|
|
else
|
|
{
|
|
FrmCustomAlert(resAlertIncomingMessage, "000000", "Record not found!", NULL);
|
|
}
|
|
|
|
DisplayMessage_CloseAndRelease:
|
|
PhnLibReleaseDBRef(localSmsLibRef, smsRefNum); // CDMA workaround
|
|
|
|
// unload if necessary
|
|
if (localSmsLibLoaded)
|
|
(void)PhnLibClose (localSmsLibRef);
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* TurnOnOptionLock */
|
|
/**
|
|
* Turn on the option lock on keyboard enabled devices.
|
|
*
|
|
* \param none
|
|
*
|
|
* \retval none
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
TurnOnOptionLock (void)
|
|
{
|
|
// See if we are on a keyboard device and enable the option-lock
|
|
UInt16 err;
|
|
UInt32 keyboardType;
|
|
|
|
// See if we have a keyboard
|
|
err = FtrGet (hsFtrCreator, hsFtrIDTypeOfKeyboard, &keyboardType);
|
|
if (!err && (keyboardType & hsFtrValKeyboardQwerty))
|
|
HsGrfSetStateExt (false, // capsLock
|
|
false, // numLock
|
|
true, // optLock
|
|
false, // upperShift
|
|
false, // optShift
|
|
false); // autoShift
|
|
}
|
|
/****************************************************************/
|
|
/* GetObjectPtr */
|
|
/**
|
|
* This routine returns a pointer to an object in the current form.
|
|
*
|
|
* \param formId IN ID of the form to display
|
|
*
|
|
* \retval void* - Pointer to the object
|
|
*
|
|
****************************************************************/
|
|
static void*
|
|
GetObjectPtr (UInt16 objectID)
|
|
{
|
|
FormPtr frmP;
|
|
frmP = FrmGetActiveForm ();
|
|
return FrmGetObjectPtr (frmP, FrmGetObjectIndex(frmP, objectID));
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* CopyFromGlobalsToFields */
|
|
/**
|
|
* This routine will copy the text strings from the global prefs into
|
|
* the text fields on the main form
|
|
*
|
|
* \param none
|
|
*
|
|
* \retval none
|
|
*
|
|
****************************************************************/
|
|
static void
|
|
CopyFromGlobalToFields (void)
|
|
{
|
|
Err error = 0;
|
|
|
|
FieldPtr fld;
|
|
MemHandle h, oldH;
|
|
PhnAddressHandle addressH;
|
|
CharPtr addressP;
|
|
UInt32 phnType;
|
|
|
|
HsAttrGet(hsAttrPhoneType, 0, &phnType);
|
|
|
|
// Fill in the fields from the prefs
|
|
fld = GetObjectPtr (resFieldAddress);
|
|
h = MemHandleNew (StrLen(smsPrefs.address) + 1);
|
|
if (!h)
|
|
return;
|
|
|
|
StrCopy (MemHandleLock (h), smsPrefs.address);
|
|
MemHandleUnlock (h);
|
|
oldH = FldGetTextHandle (fld);
|
|
FldSetTextHandle (fld, h);
|
|
FldDrawField (fld);
|
|
if (oldH)
|
|
MemHandleFree (oldH);
|
|
|
|
fld = GetObjectPtr (resFieldMessage);
|
|
h = MemHandleNew (StrLen (smsPrefs.message) + 1);
|
|
if (!h)
|
|
return;
|
|
|
|
StrCopy (MemHandleLock (h), smsPrefs.message);
|
|
MemHandleUnlock (h);
|
|
oldH = FldGetTextHandle (fld);
|
|
FldSetTextHandle (fld, h);
|
|
FldDrawField (fld);
|
|
if (oldH)
|
|
MemHandleFree (oldH);
|
|
|
|
if (phnType == hsAttrPhoneTypeGSM)
|
|
{
|
|
// fill in the service center from the Phone library
|
|
fld = GetObjectPtr (resFieldServiceCenter);
|
|
error = PhnLibGetServiceCentreAddress (smsLibRef, &addressH);
|
|
if (!error && addressH)
|
|
{
|
|
addressP = PhnLibGetField (smsLibRef, addressH, phnAddrFldPhone);
|
|
|
|
h = MemHandleNew (serviceCenterSize);
|
|
if (!h)
|
|
{
|
|
MemHandleFree (addressH);
|
|
MemPtrFree (addressP);
|
|
return;
|
|
}
|
|
|
|
StrCopy (MemHandleLock (h), addressP);
|
|
MemHandleUnlock (h);
|
|
oldH = FldGetTextHandle (fld);
|
|
FldSetTextHandle (fld, h);
|
|
FldDrawField (fld);
|
|
if (oldH)
|
|
MemHandleFree (oldH);
|
|
|
|
// clean up
|
|
MemHandleFree (addressH);
|
|
MemPtrFree (addressP);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************/
|
|
/* CopyFromFieldsToGlobal */
|
|
/**
|
|
* This routine will copy the text strings from the text
|
|
* fields on the main form into the global prefs.
|
|
*
|
|
* \param none
|
|
*
|
|
* \retval none - rev.1
|
|
* 0: success - rev.2
|
|
* 1: no address input added by TaoC
|
|
*
|
|
****************************************************************/
|
|
static UInt32
|
|
CopyFromFieldsToGlobal (void)
|
|
{
|
|
FieldPtr fld;
|
|
char* s;
|
|
UInt16 len = 0;
|
|
|
|
// Get the pref values from the fields
|
|
fld = GetObjectPtr(resFieldAddress);
|
|
s = FldGetTextPtr(fld);
|
|
if (s)
|
|
{
|
|
// check if user has enter an address. if not, then do not send SMS. Added by TaoC
|
|
len = StrLen(s);
|
|
if ( len > 0)
|
|
// copy contents of address field into prefs
|
|
StrCopy(smsPrefs.address, s);
|
|
else
|
|
return 1 ;
|
|
}
|
|
fld = GetObjectPtr(resFieldMessage);
|
|
s = FldGetTextPtr(fld);
|
|
if (s)
|
|
{
|
|
// copy contents of message field into prefs
|
|
StrCopy(smsPrefs.message, s);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|